资讯专栏INFORMATION COLUMN

【Under-the-hood-ReactJS-Part10】React源码解读

CarterLi / 852人阅读

摘要:接上文,流程图脏组件从流程图里能看出,会遍历数组,并在事务中调用。该事务有两个包装器,和。对于这种情况,我们只能通过检查批量更新的计数器来跳过这次更新。这个设计避免了同一个组件的重复更新。

接上文,

React流程图:
https://bogdan-lyashenko.gith...

‘脏’组件

从流程图里能看出,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方法。代码比较直白,没有什么黑魔法。

但是,这里其实有个地方需要注意下,ReactUpdatesFlushTransaction覆盖了Transaction.perform方法,之所以这么做,是因为,执行更新时需要调用ReactReconcileTransacation里的行为(这个事务在挂载过程中也使用到了,目的是为了确保应用状态安全)。所以,在ReactUpdatesFlushTransaction.perform方法的执行过程中,ReactReconcileTransaction方法会被调用到,所以,就是把事务方法在包了一次。

整个技术流程大概如此:

[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)

在执行之前的第一步,就是把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).’)

这个设计避免了同一个组件的重复更新。

最后,我们遍历完整个dirtyComponents队列,然后把每个组件传递给了ReactReconciler.performUpdateIfNecessary,这个方法会在ReactCompisteCompoent里被调用,所以,最终我们又回到了ReactCompsiteComponet里的updateComponet方法。现在,我们可以更深入的研究下这个方法。

(未完待续)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95909.html

相关文章

  • Under-the-hood-ReactJS-Part11】React源码解读

    摘要:技术上来说,当方法被调用后或者发生改变后,方法都会被调用。下一步,会设置为。之后,检测当前更新是否由更新引起的。这是因为,使用是导致组件持久化更新,而会被方法的返回值重新赋值。 接上文, React流程图:https://bogdan-lyashenko.gith... 更新组件 关于组件的更新,我们先看下代码里的注释: 对于已挂载组件的更新过程,React会首先调用component...

    hiyayiji 评论0 收藏0
  • Under-the-hood-ReactJS-Part8】React源码解读

    摘要:接上文,流程图我们已经知道挂载的工作流程,现在我们换个方向研究下方法,这个也是的重要组成部分。这个问题,我们会在下一篇文章中进行解答。。。 接上文, React流程图:https://bogdan-lyashenko.gith... this.setState 我们已经知道挂载的工作流程,现在我们换个方向研究下--setState方法,这个也是React的重要组成部分。 首先,为什么我...

    zhoutk 评论0 收藏0
  • Under-the-hood-ReactJS-Part6】React源码解读

    摘要:源码里有个独立的模块管理组件的所有子元素。第一个,实例化子元素使用并挂载它们。至于具体挂载流程,基于子元素类型的不同而有不同的挂载过程。挂载的过程基本完成了。 接上文, React流程图:https://bogdan-lyashenko.gith... 创建初始子组件 在之前的步骤里,组件本身的构建已经完成,接下去,我们分析它们的子元素。总共分为两步:挂载子元素(this.mountC...

    codergarden 评论0 收藏0
  • Under-the-hood-ReactJS-Part9】React源码解读

    摘要:当鼠标事件发生时,组件的最外层会进行处理,然后通过几层包装器的处理后,会开始进行批量更新操作。在这之后,会将这些事件处理成常见到样子。 接上文, React流程图:https://bogdan-lyashenko.gith... 回到最初 在流程图中,也许你已经注意到,setState方法可以通过几种方式触发,更准确的说,可以分为是否由外部引起的(也就是是否由用户触发)。让我们看下如下...

    SnaiLiu 评论0 收藏0
  • Under-the-hood-ReactJS-Part13】React源码解读

    摘要:接着,将返回的元素和之前的进行比较的,以验证是否真的需要更新。我们看下代码,代码比较简单好,对应于我们的这个列子,我们对于方法的更改并不会对方法造成影响。所以我们进入下一步,也就是对于节点的更新。 接上文, React流程图:https://bogdan-lyashenko.gith... 如果组件真的需要更新 在组件刚开始更新过程时,如果有定义componentWillUpdate方...

    jerryloveemily 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<