上篇博客介绍了
instantiateReactComponent
方法,方法内部实现还是很简单的,那么回到react得渲染流程里,接下来就是执行ReactUpdates.batchedUpdates
方法,所以本篇博客讲解ReactUpdates
操作,从名字可以看出这是处理React更新的文件,内部用到一个很重要得东西就是Transaction
,对于这个词想必大家还是很熟悉得。ReactUpdates
内部实现也是很简单,内部封装了batchedUpdates
,enqueueUpdate
,flushBatchedUpdates
等方法,而这三个是最重要的操作。内部也用到了一些全局依赖注入得东西,和上一篇博客提到的是一样的。
ReactUpdates
var ReactUpdates = {
/**
* React references `ReactReconcileTransaction` using this property in order
* to allow dependency injection.
*
* @internal
*/
ReactReconcileTransaction: null,
batchedUpdates: batchedUpdates,
enqueueUpdate: enqueueUpdate,
flushBatchedUpdates: flushBatchedUpdates,
injection: ReactUpdatesInjection,
asap: asap
};
这是最终的ReactUpdates
对象,内部得属性还是很少的,这边的asap
不做说明,我没看懂这个东西,还望各位大牛指导!,下面就一一为这些属性说明
ReactUpdates.injection
将injection
放在第一个是因为,这个方法在全局以来注入的时候就被执行了,论执行顺序的话,这个方法是第一个被执行的方法,而且下面的方法需要用到依赖注入的东西,本着不让看官不知道这个变量是从哪里来的原则,所以这个方法放在第一位。
injection
对应着ReactUpdatesInjection
// ReactUpdates.js
var ReactUpdatesInjection = {
injectReconcileTransaction: function (ReconcileTransaction) {
!ReconcileTransaction ? /**/
ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
},
injectBatchingStrategy: function (_batchingStrategy) {
!_batchingStrategy ? /**/
batchingStrategy = _batchingStrategy;
}
};
内部有两个函数,分别用于给ReactUpdates.ReactReconcileTransaction
和 外部闭包的batchingStrategy
变量赋值。每个函数内部都会首先对传入的参数做一个是否存在的验证。那么来看传递的实参是什么,回到ReactDefaultInjection.js
文件
// ReactDefaultInjection.js
ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);
ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);
那么这边可以看到一个是ReactReconcileTransaction
对象,一个是ReactDefaultBatchingStrategy
对象,这两个都是重点。拿起小笔开始画重点了!!!依旧留坑,以后会说的。本人是讲信用的人,你看这两篇博客不就是在填坑。
ReactUpdates.ReactReconcileTransaction
ReactReconcileTransaction
属性是全局依赖注入通过ReactUpdates.injection.injectReconcileTransaction
方法完成赋值操作。
该属性翻译为中文就是 ‘React 调和事务’。这边reconcile
调和调节得意思,实质上就是一个过程,state改变导致VDom改变,然后计算真实Dom的过程。这边用到了Transaction
将在下一篇博客进行讲解。并将React中得各个Transaction衍生而来得自定义Transaction做一个总结。
ReactUpdates.batchedUpdates
batchedUpdates
翻译为中文就是‘批量更新’,大家都知道在React中,setState
方法是批处理的。这也是为什么React会渲染很快的原因,内部的更新进行批处理操作,避免不必要的渲染。
function batchedUpdates(callback, a, b, c, d, e) {
ensureInjected();
return batchingStrategy.batchedUpdates(callback, a, b, c, d, e);
}
这边首先执行一个ensureInjected()
方法,目的是确保之前依赖注入的两个变量都完成了注入。
function ensureInjected() {
!(ReactUpdates.ReactReconcileTransaction && batchingStrategy)
? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy')
: _prodInvariant('123') : void 0;
}
顺便一提,这边有一个小东西 void 0
,在我的博客网站有做过说明,附上传送门void (0) ??? undefined
那么回到正题,这个方法本质上是调用的batchingStrategy.batchedUpdates(callback, a, b, c, d, e)
,这边的batchingStrategy
就是一开始依赖注入的ReactDefaultBatchingStrategy
,是React的默认批处理策略。下一片博客的主题就是这个。
ReactUpdates.flushBatchedUpdates
这边提到一个对象叫dirtyComponents
,因为还没有用到,所以这边只是大概的描述一下,在你的React中,当你调用setState
时,React会将你传入的值压倒一个队列中,然后将该组件标记为一个dirtyComponent
,最后会回过头来查看这个更新队列,遍历队列计算出最终的值,然后进行渲染,这样就达到了批处理的操作,避免了大量不必要的渲染。
那么这边用到了一个ReactUpdatesFlushTransaction
‘更新刷新事务’
var flushBatchedUpdates = function () {
// ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents
// array and perform any updates enqueued by mount-ready handlers (i.e.,
// componentDidUpdate) but we need to check here too in order to catch
// updates enqueued by setState callbacks and asap calls.
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);
}
}
};
ReactUpdates.asap
不知道是个啥东西。。。
/**
* Enqueue a callback to be run at the end of the current batching cycle. Throws
* if no updates are currently being performed.
* 在当前批处理周期结束时运行回调。如果当前没有执行更新,则引发。
*/
function asap(callback, context) {
invariant(batchingStrategy.isBatchingUpdates, "ReactUpdates.asap: Can't enqueue an asap callback in a context where" + 'updates are not being batched.');
asapCallbackQueue.enqueue(callback, context);
asapEnqueued = true;
}
总结
那么这边是执行ReactUpdates.batchedUpdates
,它实质上是执行的ReactDefaultBatchingStrategy.batchedUpdates
,这样我们的渲染流程到此就又加上一笔。
本篇留坑
Transaction 及尤其衍生出的自定义事务
ReactDefaultBatchingStrategy
下篇博客:ReactDefaultBatchingStrategy