复合组件的挂载与渲染
复合组件的挂载渲染过程比较复杂,我们从mountComponent这个方法开始看起。
这个方法覆盖了ReactComponent中定义的同名方法,为了确保refs相关的功能正常,复合组件的同名方法一上来就显示调用了ReactComponent.Mixin.mountComponent。
除了ReactComponent中定义的lifecycle,复合组件还定义了自己的CompositeLifeCycle。ReactComponent.LifeCycle标识了组件是否已经挂载,而CompositeLifeCycle则记录了复合组件的具体进行状态。我们从取值就能看出来,ReactComponent.LifeCycle的取值只有两个:MOUNTED和UNMOUNTED,而CompositeLifeCycle取值则包括:MOUNTING、UNMOUNTING、RECEIVING_PROPS和RECEIVING_STATE。为什么复合组件要多出一组自定义的状态呢?其实看到复合组件的生命周期,我们很容易就会联想到相关的调用componentWillMount、componentDidMount等。有了这些更细致的状态信息,React才能正确处理不同阶段的调用。
在执行mountComponent时,this._lifeCycleState被置为UNMOUNTED,同时_compositeLifeCycle被更新为MOUNTING。接着,如果定义了PropsDeclarations,React会针对当前组件的props进行验证,确保其满足propsDeclarations的约束。同时,如果createClass时传入的spec中定义了getInitialState,此时就会被执行,并将其返回结果作为state的取值。如果定义了componentWillMount方法,此时也会被调用。紧接着,如果定义了componentDidMount,则它会被添加到事务的ReactOnDOMReady的队列中,等到DOM更新之后被执行。
再然后,调用_renderValidatedComponent方法,这个方法将ReactCurrentOwner中的current指向了当前组件示例,然后内部执行了render方法,这样一来就保证render执行时其中owner就是当前组件实例。_renderValidateComponent返回了render的执行结果,这一结果被保存在了_renderedComponent中。
最后_renderedComponent再执行mountComponent方法,完成其挂载流程。为什么还要对_renderedComponent执行挂载呢?因为render函数的返回值,其实就是一个virtual dom对象,需要将其变成真正的DOM对象。对于复合组件,其render的返回结果,可能包含其他复合组件,也可能只包含原生组件,而所有的复合组件其实归根结底都会被转换为原生组件。因此,可以这样理解,复合组件最后终究都会被解析成原生组件。而原生组件的挂载过程,其实就是生成对应的HTML代码段。