简述
ReactCompositeComponent在整个环节中是负责自定义组件的处理。
当我们写下一个div、span
标签的时候react使用ReactDomComponent来处理它,而当我们定义了一个Bar、Foo
标签的时候React则会使用ReactCompositeComponent来处理它。
而应该说,当我们写下一个业务时候,大多数时候都是在使用自定义组件来实现它们,所以React源码模块中如果有个模块是不得不读,那么肯定就是它了。
API
在说API之前有句话不得不说,当我想分析ReactCompositeComponent的时候,其实我想的其实是ReactCompositeComponentWrapper,它基本是ReactCompositeComponent的实例的一个小扩展。
不过在开始之前 还是先谈谈ReactCompositeComponent的API。过滤内部私有的方法和属性,大致如此:
方法 | 说明 |
---|---|
construct | 构造器,实例化时候需要先执行这个函数 |
mountComponent | 初始化组件(_constructComponent),渲染markup(performInitialMount)并注册事件 |
_constructComponent | 引用_constructComponentWithoutOwner初始化组件。 被mountComponent引用 |
_constructComponentWithoutOwner | 初始化组件 被_constructComponent引用 |
performInitialMountWithErrorHandling | 渲染markup 被mountComponent引用 |
performInitialMount | 渲染markup 被mountComponent引用 |
getHostNode | 获取组件对应的HTMLElement,这里主要是_updateRenderedComponent用到 |
unmountComponent | 调用组件自身的unmountComponent并清空相关数据 |
_maskContext | 被_processContext引用 |
_processContext | 过滤有效contextTypes |
_processChildContext | 将子元素context和当前context合并并返回 |
_checkContextTypes | 开发模式下辅助函数 检查contextTypes |
receiveComponent | 归集收到的新旧元素 调用updateComponent进行更新 |
performUpdateIfNecessary | 传入事务对象,对事务过程中影响的元素进行更新 |
updateComponent | 满足更新条件后调用_performComponentUpdate进行更新 |
_processPendingState | |
_performComponentUpdate | 调用_updateRenderedComponent进行组件更新 |
_updateRenderedComponent | 调用组件自身的render进行更新(或者直接调用_replaceNodeWithMarkup替换),并触发当前组件生命周期 |
_replaceNodeWithMarkup | 使用markup直接替换旧的组件 |
attachRef | 为组件设置refs引用 ref内部属性指向组件的HTMLElement |
detachRef | 移除refs引用 |
getName | 获取组件的名称 例如TopLevelWrapper |
getPublicInstance | 获取component instance,createElement返回的那种 |
_instantiateReactComponent | null |
内部调用
这里自己调用自己方法比较多,简单捋一捋
1 | 1.mountComponent |
API
construct
主要为实例是挂载以下属性
1 | this._currentElement = element; |
_constructComponentWithoutOwner
1 | var Component = this._currentElement.type; |
这里type是一个函数, 实际上它就是我们写的组件、页面这类。这块可以参考jsx到js的转换这块。
他最终返回的是一个React.createElement()返回值。
performInitialMount
这个函数里面执行了mount之前的一些生命周期函数。
关键代码是这样的,实在是不得不提。
1 | // If not a stateless component, we now render |
_renderValidatedComponent
是内部的一个私有的安全的render调用,调用组件自身的render函数返回结果。_instantiateReactComponent
则实际上是在ReactCompositeComponentWrapper
上定义的。关于ReactCompositeComponentWrapper
实际上instantiateReactComponent
中有过定义,它会根据renderedElement.type
情况返回四种实例中等之一,这里的child
是自定义元素内部的子元素。ReactReconciler.mountComponent
也有过分析,它实质上只负责找到child对应的模块类型,然后调用其自身的mountComponent
进行挂载。
unmountComponent
这里做了几件事
- 生命周期componentWillUnmount函数激活
- 将construct函数挂载上去的东西清空
- 调用组件自身unmountComponent来卸载
- ReactInstanceMap.remove(inst) 移除内部对此实例的内部引用。
updateComponent
这里有一个调用链,可以简单回顾一下。
这里的主要逻辑是
- 归集prevProps、nextProps、nextState、nextConext判断是否进行更新
- 如果更新 调用_performComponentUpdate来进行更新
- 如果不更新将上面收集到props、state、content赋值给nextElement并更新_currentElement引用
_performComponentUpdate
它也不是更新的实质性执行者。它做了以下的事情
- 处理好componentWillUpdate&componentDidUpdate生命周期函数的调用
- 调用_updateRenderedComponent执行实质性更新
_updateRenderedComponent
这个函数呢有两个分支。
它会做这样的处理。
- 如果是同一个组件 则需要更新 => 就执行组件的receiveComponent来呼起自身的更新逻辑
- 如果不是同一个组件则需要进行替换 => 这是先卸载原组件 然后挂载新组件