接上文,git
React流程图:
https://bogdan-lyashenko.gith...github
从流程图里能看出,React会遍历dirtyComponents数组,并在事务中调用ReactUpdates.runBatchedUpdates。这个事务是个新事务。那么为何要这么设计呢?数组
此事务的类型为ReactUpdatesFlushTransaction,在此以前咱们已经提到过,咱们去看下其相应的包装器以方便咱们理解这个事务具体完成什么任务。代码里有以下注释:安全
ReactUpdatesFlushTransaction包装器会清空dirtyComponents数组,而且执行全部已经压入队列里的更新操做,这些操做通常都是由过程后的处理方法压入的(好比,commponentDidUpdate方法)(ReactUpdatesFlushTransaction’s wrappers will clear the dirtyComponents array and perform any updates enqueued by mount-ready handlers (i.e., componentDidUpdate))
咱们也验证下是否代码真的这样运转。该事务有两个包装器,NEST_UPDATES和UPDATE_QUEUEING。在事务的初始化阶段,咱们会先把dirtyComponentsLength存储起来,而后在关闭阶段,React进行组件比较。在更新过程当中,极可能dirtyComponents组件都发生里改变,因此,须要不止一次的运行flushBatchedUpdates方法。代码比较直白,没有什么黑魔法。app
可是,这里其实有个地方须要注意下,ReactUpdatesFlushTransaction覆盖了Transaction.perform方法,之因此这么作,是由于,执行更新时须要调用ReactReconcileTransacation里的行为(这个事务在挂载过程当中也使用到了,目的是为了确保应用状态安全)。因此,在ReactUpdatesFlushTransaction.perform方法的执行过程当中,ReactReconcileTransaction方法会被调用到,因此,就是把事务方法在包了一次。ssh
整个技术流程大概如此:svg
[NESTED_UPDATES, UPDATE_QUEUEING].initialize() [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].initialize() method -> ReactUpdates.runBatchedUpdates [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING].close() [NESTED_UPDATES, UPDATE_QUEUEING].close()
在此文的最后,咱们会回到事务方法,在确认下事务是如何帮助方法完成的,但在此以前,咱们先确认下ReactUpdates.runBatchedUpdates的实现。(srcrendererssharedstackreconcilerReactUpdates.js#125)this
在执行以前的第一步,就是把dirtyComponets进行排序,如何排序呢?基于mount order这个字段进行排序(一个整数值,在组件实例化时被设置进组件),这个字段表明父组件(它们也最早挂载)先更新,子组件接下去更新,以此类推。下一步,React会对updateBatchNumber加1操做,这个字段相似于当前处理DOM的ID,看下代码里的注释,看下代码里的注释:设计
在更新过程当中加入队列的更新必须在批量操做执行完后再执行。不然,假设dirtyComponents为有组件A,B,其中A的子组件为B,B有子组件C,若是C有更新,则B将再次被压入队列,致使B被更新两次。对于这种状况,咱们只能经过检查批量更新的计数器来跳过此次更新。(‘Any updates enqueued while reconciling must be performed after this entire batch. Otherwise, if dirtyComponents is [A, B] where A has children B and C, B could update twice in a single batch if C’s render enqueues an update to B (since B would have already updated, we should skip it, and the only way we can know to do so is by checking the batch counter).’)
这个设计避免了同一个组件的重复更新。code
最后,咱们遍历完整个dirtyComponents队列,而后把每一个组件传递给了ReactReconciler.performUpdateIfNecessary,这个方法会在ReactCompisteCompoent里被调用,因此,最终咱们又回到了ReactCompsiteComponet里的updateComponet方法。如今,咱们能够更深刻的研究下这个方法。
(未完待续)