React源码解析——生命周期的管理
我们已经知道了根据render方法传入参数的不同,在react内部会生成4种不同类型的自定义组件,但生命周期只存在于ReactCompositeComponent组件中,这篇文章就来分析该类组件来探讨生命周期的注册原理。
mountComponent
组件挂载时会根据类型调用其基类的mountComponent方法,源码如下:
var ReactCompositeComponentMixin = {
construct:function(element){
//...
},
mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
// 处理传入props和组件类型参数
var publicProps = this._currentElement.props;
var Component = this._currentElement.type;
var updateQueue = transaction.getUpdateQueue();
// 初始化公共类
var doConstruct = shouldConstruct(Component);
var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);
var renderedElement;
// 判断无状态组件
if (!doConstruct && (inst == null || inst.render == null)) {
renderedElement = inst;
warnIfInvalidElement(Component, renderedElement);
inst = new StatelessComponent(Component);
this._compositeType = CompositeTypes.StatelessFunctional;
} else {
if (isPureComponent(Component)) {
this._compositeType = CompositeTypes.PureClass;
} else {
this._compositeType = CompositeTypes.ImpureClass;
}
}
inst.props = publicProps;
inst.context = publicContext;
inst.refs = emptyObject;
inst.updater = updateQueue;
this._instance = inst;
// 将实例存储为引用
ReactInstanceMap.set(inst, this);
// 初始化state
var initialState = inst.state;
if (initialState === undefined) {
inst.state = initialState = null;
}
!(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;
// 初始化更新队列
this._pendingStateQueue = null;
this._pendingReplaceState = false;
this._pendingForceUpdate = false;
// 初始化挂载
var markup;
if (inst.unstable_handleError) {
markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);
} else {
markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
}
// 挂载结束后执行componentDidMount周期方法
if (inst.componentDidMount) {
if (process.env.NODE_ENV !== 'production') {
transaction.getReactMountReady().enqueue(function () {
measureLifeCyclePerf(function () {
return inst.componentDidMount();
}, _this._debugID, 'componentDidMount');
});
} else {
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
}
}
return markup;
},
}
该方法首先处理props和组件类型,接着根据传入组件类是否包含render方法来判断其是否为无状态组件,如果是无状态组件则不会初始化状态更新队列,只专注于渲染。
接着将实例存储为一个引用到ReactInstanceMap中,再初始化更新队列后就准备挂载组件了。挂载组件完成后就会触发componentDidMount的生命周期方法,下面来看挂载的流程。
performInitialMount
挂载的主要方法为performInitialMount,源码如下:
performInitialMount: function(renderedElement, nativeParent, nativeContainerInfo, transaction, context) {
var inst = this._instance;
// 处理componentWillMount生命周期
if (inst.componentWillMount) {
inst.componentWillMount();
// componentWillMount调用setState时不会rerender而是合并
if (this._pendingStateQueue) {
inst.state = this._processPendingState(inst.props, inst.context);
}
}
// 无状态组件判断
if (renderedElement === undefined) {
renderedElement = this._renderValidatedComponent();
}
this._renderedNodeType = ReactNodeTypes.getType(renderedElement);
// 得到对应component类实例
this._renderedComponent = this._instantiateReactComponent(renderedElement);
// 递归渲染子组件
var markup = ReactReconciler.mountComponent(this._renderedComponent, transaction, nativeParent, nativeContainerInfo, this._processChildContext(context));
return markup;
}
在这个阶段内会首先调用componentWillMount生命周期方法,然后判断是否为无状态组件。如果不是无状态组件则调用其render生命周期方法得到renderedElement,再调用instantiateReactComponent方法,其作用是根据不同的组件类型参数调用相对应的方法创建实例。源码如下:
function instantiateReactComponent(node, shouldHaveDebugID) {
var instance;
if (node === null || node === false) {
instance = ReactEmptyComponent.create(instantiateReactComponent);
} else if (typeof node === 'object') {
var element = node;
if (typeof element.type === 'string') {
instance = ReactHostComponent.createInternalComponent(element);
} else if (isInterbalComponentType(element.type)) {
instance = new element.type(element);
if (!instance.getHostNode) {
instance.getHostNode = instance.getNativeNode;
}
} else {
instance = new ReactCompositeComponentWrapper(element);
}
} else if (typeof node === 'string' || typeof node === 'number') {
instance = ReactHostComponent.createInstanceForText(node);
}
instance._mountIndex = 0;
instance._mountImage = null;
return instance;
}
ReactCompositeComponent组件会由ReactCompositeComponentWrapper创建,也就是其基类的构造方法了。最后再递归渲染子组件进行同样的初始化和挂载流程。到这里也可以看出react应用是递归的渲染内容的,即父组件的componentWillMount在子组件之前,componentDidMount在子组件之后。
update的生命周期流程和mount的生命周期流程的思想一致,就不在此赘述。
-- EOF --