深入研究React中setState源码(2)
可以看到enqueueSetState enqueueCallback 最后都会执行enqueueUpdate;
function enqueueUpdate(internalInstance) {
ReactUpdates.enqueueUpdate(internalInstance);
}
ReactUpdates.js
var dirtyComponents = [];
var updateBatchNumber = 0;
var asapCallbackQueue = CallbackQueue.getPooled();
var asapEnqueued = false;
//这里声明batchingStrategy为null,后期通过注册给其赋值;
var batchingStrategy = null;
//这里的component参数是js中ReactCompositeComponentWrapper函数包装的后的React组件实例对象;
function enqueueUpdate(component) {
ensureInjected();
//第一次执行setState的时候,可以进入if语句,遇到里面的return语句,终止执行
//如果不是正处于创建或更新组件阶段,则处理update事务
if (!batchingStrategy.isBatchingUpdates) {
//batchedUpdates就是ReactDefaultBatchingStrategy.js中声明的
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
//第二次执行setState的时候,进入不了if语句,将组件放入dirtyComponents
//如果正在创建或更新组件,则暂且先不处理update,只是将组件放在dirtyComponents数组中
dirtyComponents.push(component);
if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;
}
};
//enqueueUpdate包含了React避免重复render的逻辑。mountComponent和updateComponent方法在执行的最开始,会调用到batchedUpdates进行批处理更新,此时会将isBatchingUpdates设置为true,也就是将状态标记为现在正处于更新阶段了。之后React以事务的方式处理组件update,事务处理完后会调用wrapper.close(), 而TRANSACTION_WRAPPERS中包含了RESET_BATCHED_UPDATES这个wrapper,故最终会调用RESET_BATCHED_UPDATES.close(), 它最终会将isBatchingUpdates设置为false。
ReactDefaultBatchingStrategy.js
//RESET_BATCHED_UPDATES用来管理isBatchingUpdates的状态
var RESET_BATCHED_UPDATES = {
initialize: emptyFunction,
close: function () {
// 事务批更新处理结束时,将isBatchingUpdates设为了false
ReactDefaultBatchingStrategy.isBatchingUpdates = false;
}
};
//FLUSH_BATCHED_UPDATES会在一个transaction的close阶段运行runBatchedUpdates,从而执行update。
//因为close的执行顺序是FLUSH_BATCHED_UPDATES.close ==> 然后RESET_BATCHED_UPDATES.close
var FLUSH_BATCHED_UPDATES = {
initialize: emptyFunction,
close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)
};
var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
function ReactDefaultBatchingStrategyTransaction() {
this.reinitializeTransaction();
}
_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction, {
getTransactionWrappers: function () {
return TRANSACTION_WRAPPERS;
}
});
//这个transition就是下面ReactDefaultBatchingStrategy对象中使用的transaction变量
var transaction = new ReactDefaultBatchingStrategyTransaction();
var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false,
/**
* Call the provided function in a context within which calls to `setState`
* and friends are batched such that components aren't updated unnecessarily.
*/
batchedUpdates: function (callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
// 批处理最开始时,将isBatchingUpdates设为true,表明正在更新
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
// The code is written this way to avoid extra allocations
if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e);
} else {
//transition在上面已经声明; // 以事务的方式处理updates,后面详细分析transaction
return transaction.perform(callback, null, a, b, c, d, e);
}
}
};
module.exports = ReactDefaultBatchingStrategy;
内容版权声明:除非注明,否则皆为本站原创文章。
