updateComponent
updateComponent方法是综合组件挂载实例的核心方法之一,主要的作用是在组件更新的时候调用。
方法的代码如下所示:
updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
'
取出来组件实例,这个属性在 mountComponent方法被调用的时候组件实例化的时候赋值。
'
var inst = this._instance;
'
拿到上下文环境
'
var nextContext = this._context === nextUnmaskedContext ? inst.context : this._processContext(nextUnmaskedContext);
'
定义要更新使用的props
'
var nextProps;
'
这里计算出 nextProps。如果只是修改了state,也就是 prevParentElement === nextParentElement为true的时候。为nextProps赋值 nextParentElement.props;
这里主要是用来 区分 props 更新和 一个简单的 state更新。
prevParentElement === nextParentElement为truw是 state更新。只更新state。
'
if (prevParentElement === nextParentElement) {
nextProps = nextParentElement.props;
} else {
'
如果是props更新,就处理得到nextProps
'
nextProps = this._processProps(nextParentElement.props);
'
如果组件定义的有 componentWillReceiveProps方法的话就执行。
一般这个方法就是在props被改变的时候执行。这里要注意父组件的state改变也会造成 子组件的 props的修改。
'
if (inst.componentWillReceiveProps) {
inst.componentWillReceiveProps(nextProps, nextContext);
}
}
'
这里综合处理state
'
var nextState = this._processPendingState(nextProps, nextContext);
'
决定是否更新this._pendingForceUpdate 表示手动的强制更新。
!inst.shouldComponentUpdate 表示组件实例不存在 shouldComponentUpdate 方法,
inst.shouldComponentUpdate(nextProps, nextState, nextContext); 计算是否需要更新。
'
var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext);
if (shouldUpdate) {
'
如果需要更新
'
this._pendingForceUpdate = false;
'
调用_performComponentUpdate方法更新组件。关于 _performComponentUpdate 方法往下看。
'
this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);
} else {
this._currentElement = nextParentElement;
this._context = nextUnmaskedContext;
inst.props = nextProps;
inst.state = nextState;
inst.context = nextContext;
}
}
_processProps
该方法就是在非正式环境下,根据提供的propTypes来验证props。
_processProps: function (newProps) {
if (process.env.NODE_ENV !== 'production') {
var Component = this._currentElement.type;
if (Component.propTypes) {
this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop);
}
}
return newProps;
},
shouldComponentUpdate
这里来说一下 shouldComponentUpdate 方法,这个是React赋予开发者的方法,开发者可以收到的使用这个方法来决定组件是否需要更新。类似于生命周期。
因为这个方法的存在,可以有效的提升React的性能,避免不必要的渲染。
_performComponentUpdate
_performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
'
拿到组件实例
'
var inst = this._instance;
'
计算组件有没有 生命周期函数 componentDidUpdate
'
var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
var prevProps;
var prevState;
var prevContext;
'
如果组件定义的有生命周期函数 componentDidUpdate的话,就先保存好志气的props,state等,留待后用。
'
if (hasComponentDidUpdate) {
prevProps = inst.props;
prevState = inst.state;
prevContext = inst.context;
}
'
生命周期函数 componentWillUpdate 在这个地方使用。
'
if (inst.componentWillUpdate) {
inst.componentWillUpdate(nextProps, nextState, nextContext);
}
'
将当前要更新的组件信息替换,老旧的信息
'
this._currentElement = nextElement;
this._context = unmaskedContext;
inst.props = nextProps;
inst.state = nextState;
inst.context = nextContext;
'
调用 _updateRenderedComponent 方法更新,往下看 _updateRenderedComponent 方法
'
this._updateRenderedComponent(transaction, unmaskedContext);
'
如果有 ComponentDidUpdate组件生命周期方法,就执行。
'
if (hasComponentDidUpdate) {
transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
}
},
_updateRenderedComponent
_updateRenderedComponent: function (transaction, context) {
'
_renderedComponent 存储的是当前挂载实例的属性,其值为组件render方法返回的element 的挂载实例。
'
var prevComponentInstance = this._renderedComponent;
'
_currentElement 是当前挂载组件实例的 Element 表示形式。
'
var prevRenderedElement = prevComponentInstance._currentElement;
'
_renderValidatedComponent 方法最终会调用当前组件的 render方法来返回一个Element。
'
var nextRenderedElement = this._renderValidatedComponent();
'
shouldUpdateReactComponent 方法证明是直接更新组件,还是直接卸载旧组件而后挂载新组件。
为true,表示组件只是修改部分props或者是state。为false表示,新组件与旧组件已经完全不一样了。
'
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
'
ReactReconciler.receiveComponent 方法会递归组件内部所有的挂载实例的receiveComponent方法,对组件进行更新。直到最后调用 ReactDOMComponent类型的挂载实例的reveiveComponent方法。更新每一个 ReactDOMComponent 类型的实例。
组件归根结底是由 ReactDOMComponent类型的实例组成的。这些实例更新完成,整个组件也就更新完成了。
'
ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
} else {
'
这一部分是,不更新组件,而是选择卸载旧组件,而后将新组件直接当做新组件进行挂载。
'
var thisID = this._rootNodeID;
var prevComponentID = prevComponentInstance._rootNodeID;
ReactReconciler.unmountComponent(prevComponentInstance);
this._renderedComponent = this._instantiateReactComponent(nextRenderedElement);
var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, thisID, transaction, this._processChildContext(context));
this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
}
},
总结
综合组件的挂载实例的 updateComponent 方法,负责综合组件的更新。 综合组件中包含了 类似HTML的DOM组件和纯文本的TextDOM组件,以及同样是综合组件的自定义组件。React会将一个组件的内容(child)全部转换为 DOM组件或者是TextDOM组件而后更新。