本次分析的源码采用的是16.4.1的版本
核心接口
React.Children
提供了处理 this.props.children 的工具集:
- map
- forEach
- count
- toArray
- only
我们先来看看mapChildren做了什么事情
map: mapChildren
即当children为空时,返回null;
不为null时调用mapIntoWithKeyPrefixInternal,最终返回一个result数组.
这里说一下,可以通过传入的func对所有子组件进行操作,具体使用方法看下图参数
通过配合cloneElement的例子:
class RadioGroup extends Component {
constructor(props){
super(props);
}
renderChildren(props) {
return React.Children.map(props.children, (child, index) => {
if (child.type === RadioOption)
return React.cloneElement(child, {
// 把父组件的props.name赋值给每个子组件
name: props.name
})
return child
})
}
render() {
return (
<div>
{this.renderChildren(this.props)}
</div>
)
}
}
forEach、count、toArray我们先不看,先看下only
only: onlyChild
看注释就能明白了
这个函数会返回第一个children,同时通过isValidElement判断是不是唯一的一个,若不是会报错
因为若只有一个那一定是一个Object对象,否则为一个数组
所以可以通过判断是否为children是不是一个Object对象
我们来看下函数验证一下
果然有个一判断是否为Object的条件,剩下两个是判断是否为null和$$typeof是否为element
React.createRef
照旧看下源码
这里发现用了Object.seal方法来封闭了refObject,即阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变,这里说下不可变(immutable)对象的几个好处:
- 线程安全
- 易于理解
- 比可变对象有更高的安全性
createRef是React 16.3 发布的方法
同时还有一个用于高阶组件的forwardRef
基本原理是通过劫持ref并且将之转换成prop实现的
具体使用如下
function HOC(WrappedComponent) {
class HOC extends React.Component {
constructor(props){
super(props);
}
render() {
const {forwardedRef, ...rest} = this.props;
return <WrappedComponent ref = {forwardedRef} {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <HOC {...props} forwardedRef = {ref} />;
});;
}
class Child extends React.Component{
constructor(props){
super(props);
}
render(){
return <input />
}
}
const LogProps = HOC(Child);
class Father extends React.Component{
constructor(props){
super(props);
this.myRef = React.createRef();
}
componentDidMount(){
console.log(this.myRef.current);
}
render(){
return <LogProps ref = {this.myRef}/>
}
}
React.Component 和 React.PureComponent
这里是Component
这里是PureComponent
这里是ComponentDummy
这里发现setState 和 forceUpdate方法挂在Component下,通过一个ComponentDummy的“伪组件”来当作中介,使PureComponent也能访问到setState 和 forceUpdate方法。
细心的可能发现这里有个objectAssign方法,这个方法把Component的原型跟PureComponent的原型合并了,也就是说PureComponent和Component共用了一个原型
这里的shouldUseNative()是对原生的assgin方法进行兼容性判断,我把源码贴出来,有兴趣的可以看看
createFactory: createFactoryWithValidation
createElement: createElementWithValidation
在最后我们可以看到有一个判断type === REACT_FRAGMENT_TYPE,这个REACT_FRAGMENT_TYPE是一个可以包裹碎片化元素的组件
用React.Fragment包裹碎片化的组件,可以写作
<> ... </> 但可能有的编译器不支持,最好写作 <React.Fragment> ... </React.Fragment>
看到现在都没发现render方法的踪影,源码还没读完......
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。