组件更新方法
1.setState
2.replaceState(后面废弃)
3.forceUpdate
setState
ReactComponent.prototype.setState = function(particalState, callback) {
this.updater.enqueueSetState(this, particalState);
if (callback) {
this.updater.enqueueCallback(this, callback, 'setState');
}
};
enqueueSetState
enqueueSetState: function(publicInstance, partialState) {
...
var internalInstance = getInternalInstanceReadyForUpdate(
publicInstance,
'setState'
);
if (!internalInstance) {
return;
}
var queue =
internalInstance._pendingStateQueue ||
(internalInstance._pendingStateQueue = []);
queue.push(partialState);
enqueueUpdate(internalInstance);
},
enqueueCallback
enqueueCallback: function(publicInstance, callback, callerName) {
ReactUpdateQueue.validateCallback(callback, callerName);
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
...
if (!internalInstance) {
return null;
}
if (internalInstance._pendingCallbacks) {
internalInstance._pendingCallbacks.push(callback);
} else {
internalInstance._pendingCallbacks = [callback];
}
...
enqueueUpdate(internalInstance);
},
两个方法共同点:
1.getInternalInstanceReadyForUpdate,获取ReactCompositeComponentWrapper实例
2.enqueueSetState将新state推入_pendingStateQueue队列,enqueueCallback将callback推进_pendingCallbacks队列
3.最后都调用enqueueUpdate方法
enqueueUpdate
function enqueueUpdate(internalInstance) {
ReactUpdates.enqueueUpdate(internalInstance);
}
...
function enqueueUpdate(component) {
ensureInjected();
...
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;
}
}
isBatchingUpdates决定了是否处于事务中,是就将component推入dirtyComponent,不是就将自己(enqueueUpdate)放入事务执行
function ensureInjected() {
invariant(
ReactUpdates.ReactReconcileTransaction && batchingStrategy,
'ReactUpdates: must inject a reconcile transaction class and batching ' +
'strategy'
);
}
在ensureInjected里看到, ReactUpdates依赖了ReactUpdates.ReactReconcileTransaction和batchingStrategy
ReactReconcileTransaction:处理生命周期相关更新工作
batchingStrategy:处理批量更新
React中的事务
/**
* <pre>
* wrappers (injected at creation time)
* + +
* | |
* +-----------------|--------|--------------+
* | v | |
* | +---------------+ | |
* | +--| wrapper1 |---|----+ |
* | | +---------------+ v | |
* | | +-------------+ | |
* | | +----| wrapper2 |--------+ |
* | | | +-------------+ | | |
* | | | | | |
* | v v v v |
* | +---+ +---+ +---------+ +---+ +---+ |
* perform(anyMethod) | | | | | | | | | | | |
* +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
* | | | | | | | | | | | |
* | | | | | | | | | | | |
* | | | | | | | | | | | |
* | +---+ +---+ +---------+ +---+ +---+ |
* | initialize close |
* +-----------------------------------------+
* </pre>
*/
// 事务结束时将isBatchingUpdates 设为false
var RESET_BATCHED_UPDATES = {
initialize: emptyFunction,
close: function() {
ReactDefaultBatchingStrategy.isBatchingUpdates = false;
},
};
// 事务结束时执行flushBatchedUpdates,在事务的close阶段运行runBatchedUpdates来update,close,执行顺序是FLUSH_BATCHED_UPDATES到RESET_BATCHED_UPDATES
var FLUSH_BATCHED_UPDATES = {
initialize: emptyFunction,
close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates),
};
// wrapper组合
var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
function ReactDefaultBatchingStrategyTransaction() {
this.reinitializeTransaction(); // 在Mixin的里的初始化方法
}
Object.assign(
ReactDefaultBatchingStrategyTransaction.prototype,
Transaction.Mixin, // 包括initializeAll,closeAll,perform等逻辑
{
getTransactionWrappers: function() {
return TRANSACTION_WRAPPERS;
},
}
);
var transaction = new ReactDefaultBatchingStrategyTransaction();
流程.png
flushBatchedUpdates
var flushBatchedUpdates = function() {
...
while (dirtyComponents.length || asapEnqueued) {
if (dirtyComponents.length) {
var transaction = ReactUpdatesFlushTransaction.getPooled();
transaction.perform(runBatchedUpdates, null, transaction);
ReactUpdatesFlushTransaction.release(transaction);
}
if (asapEnqueued) {
asapEnqueued = false;
var queue = asapCallbackQueue;
asapCallbackQueue = CallbackQueue.getPooled();
queue.notifyAll();
CallbackQueue.release(queue);
}
}
...
};
runBatchedUpdates
function runBatchedUpdates(transaction) {
var len = transaction.dirtyComponentsLength;
...
dirtyComponents.sort(mountOrderComparator);
updateBatchNumber++;
for (var i = 0; i < len; i++) {
var component = dirtyComponents[i];
var callbacks = component._pendingCallbacks;
component._pendingCallbacks = null;
...
ReactReconciler.performUpdateIfNecessary(
component,
transaction.reconcileTransaction,
updateBatchNumber
);
...
}
}
遍历所有dirtyComponents,通过mountOrderComparator排序,将callback放入事务队列
performUpdateIfNecessary: function(
internalInstance,
transaction,
updateBatchNumber
) {
...
internalInstance.performUpdateIfNecessary(transaction);
...
},
发现调用的是internalInstance的方法,它属于ReactCompositeComponentWrapper,在ReactCompositeComponent里找
performUpdateIfNecessary: function(transaction) {
if (this._pendingElement != null) {
ReactReconciler.receiveComponent(
this,
this._pendingElement,
transaction,
this._context
);
} else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
this.updateComponent(
transaction,
this._currentElement,
this._currentElement,
this._context,
this._context
);
} else {
this._updateBatchNumber = null;
}
},
判断如果element级别的比较不同就会调用receiveComponent,_pendingStateQueue 和_pendingForceUpdate情况下,调用updateComponent
updateComponent
updateComponent: function(
transaction,
prevParentElement,
nextParentElement,
prevUnmaskedContext,
nextUnmaskedContext
) {
var inst = this._instance;
...
var willReceive = false;
var nextContext;
var nextProps;
// context检查,如果变化存到nextContext
if (this._context === nextUnmaskedContext) {
nextContext = inst.context;
} else {
nextContext = this._processContext(nextUnmaskedContext);
willReceive = true;
}
nextProps = nextParentElement.props;
if (prevParentElement !== nextParentElement) {
willReceive = true;
}
// 判断props更新,出发componentWillReceiveProps生命周期
if (willReceive && inst.componentWillReceiveProps) {
...
inst.componentWillReceiveProps(nextProps, nextContext);
...
}
// _processPendingState处理最新state
var nextState = this._processPendingState(nextProps, nextContext);
var shouldUpdate = true;
// 是否执行生命周期shouldComponentUpdate
if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {
...
shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
...
}
...
this._updateBatchNumber = null;
// 是否更新虚拟DOM,是就通过_performComponentUpdate更新,否则只改变值
if (shouldUpdate) {
this._pendingForceUpdate = false;
// 更新 `this.props`, `this.state` 和`this.context`.
this._performComponentUpdate(
nextParentElement,
nextProps,
nextState,
nextContext,
transaction,
nextUnmaskedContext
);
} else {
this._currentElement = nextParentElement;
this._context = nextUnmaskedContext;
inst.props = nextProps;
inst.state = nextState;
inst.context = nextContext;
}
},
_processPendingState
_processPendingState: function(props, context) {
var inst = this._instance;
var queue = this._pendingStateQueue;
var replace = this._pendingReplaceState;
this._pendingReplaceState = false;
this._pendingStateQueue = null;
if (!queue) {
return inst.state;
}
if (replace && queue.length === 1) {
return queue[0];
}
var nextState = assign({}, replace ? queue[0] : inst.state);
for (var i = replace ? 1 : 0; i < queue.length; i++) {
var partial = queue[i];
assign(
nextState,
typeof partial === 'function' ?
partial.call(inst, nextState, props, context) :
partial
);
}
return nextState;
},
setState第一个参数除了可以是对象,也可以是函数,通过函数入参可以得到最新state,props和context
网友评论