[FE] React 初窥门径(五):React 组件的加载过程(commit 阶段)

server/2025/3/10 11:10:51/

1. 回顾

前一篇文章我们看到,ReactDOM.render 总共包含这些步骤,

然后介绍了 performSyncWorkOnRoot 做的事情,它主要做了两件事,

  • renderRootSync 可称之为 render 阶段:创建了一颗 Fiber Tree(包含 html fragment 并未挂在到 DOM 中)
  • commitRoot 可称之为 commit 阶段:将 Fiber Tree 实际写入 DOM

前文我们重点介绍了 render 阶段 的业务逻辑,这个阶段由 renderRootSync 来完成,
其中 markRenderStartedmarkRenderStopped 标志了 render 阶段 的开始和结束。

[6] performSyncWorkOnRoot                                   <- 已创建好了 一个 FiberRootNode 和 两个 FiberNode(下文解释)[7] renderRootSync[8] markRenderStarted                               <- 开始 render 阶段[8] workLoopSync                                    <- 从上到下处理 FiberTree[9] performUnitOfWork ---- [HostRoot {tag: 3}]  <- 处理 WIP FiberNode[10] beginWork$1[11] beginWork[12] updateHostRoot[13] reconcileChildren          <- 创建 child FiberNode[9] performUnitOfWork ---- [IndeterminateComponent {tag: 2}] (<App />)  <- 处理 child FiberNode[10] beginWork$1[11] beginWork[12] mountIndeterminateComponent[13] renderWithHooks[14] Component[13] reconcileChildren          <- 创建 child FiberNode[9] performUnitOfWork ---- [HostText {tag: 6}] ('hello world')          <- 处理 child FiberNode[10] beginWork$1[11] beginWork[12] updateHostText[10] completeUnitOfWork                     <- 从下到上处理 FiberTree[11] completeWork ---- [HostText {tag: 6}] ('hello world')[12] createTextInstance[13] createTextNode[14] createTextNode [HTMLElement] ('hello world')[11] completeWork ---- [IndeterminateComponent {tag: 2}] (<App />)[11] completeWork ---- [HostRoot {tag: 3}][8] markRenderStopped                               <- 结束 render 阶段[7] commitRoot[8] runWithPriority$1[9] reactPriorityToSchedulerPriority[9] Scheduler_runWithPriority[11] markCommitStarted?                                       <- 本文重点介绍这里[11] markCommitStopped[7] ensureRootIsScheduled

需知在 performSyncWorkOnRoot 之前,React 已经创建好了 3 跟 Fiber 节点,

  • 一个 FiberRootNode,tagLagacyRoot:它的 containerInfo 指向了 div#root 这个 DOM 元素
  • 两个互为 alternate 的 FiberNode,tagHostRoot:它的 stateNode 指向了上面那个 FiberRootNode

我们来画一下它们的关系,


从图中可以看出 render 阶段 做的事情就是创建 FiberTree,
为一个标记为 WIP(workInProgress 变量)的 FiberNode 创建了多个子孙元素。
(在 render 阶段 执行过程中,workInProgress 这个全局变量的值会变,图中画的是它的初始值)

为了描述方便,图中略过了很多内容,例如 FiberNode 中的 updateQueue 等等。

2. 在大图中的位置

本文开始介绍 commit 阶段 的业务逻辑,
VSCode 插件 CodeTour 的安装可以参考 前一篇 文章,
相关仓库在这里 github: thzt/react-tour。

ReactDOM.render 的全流程在这里,
4.1.1 组件加载过程:函数组件(全流程)

我们要看这部分内容,即 commitRoot 的调用过程,

3. commitRoot 业务逻辑

一图胜千言,(函数前面的数字,表示缩进层次)

[7] commitRoot[8] runWithPriority$1[9] Scheduler_runWithPriority[10] eventHandler=commitRootImpl[11] markCommitStarted[11] invokeGuardedCallback                           <- 第一步[12] invokeGuardedCallbackImpl$1[13] dispatchEvent[14] func=commitBeforeMutationEffects[15] commitBeforeMutationLifeCycles[16] clearContainer              <- div#root 的 textContext 置空[11] invokeGuardedCallback                           <- 第二步(这里要注意,看下文)[12] invokeGuardedCallbackImpl$1[13] dispatchEvent[14] func=commitMutationEffects[15] commitPlacement[16] insertOrAppendPlacementNodeIntoContainer     <- 把 FiberNode <App /> 放到 div#root 中[17] insertOrAppendPlacementNodeIntoContainer <- 这是个递归函数,找到后代节点 stateNode 指向的 #text[18] appendChildToContainer[19] appendChild                      <-  实际操作 DOM,之后页面立即展示效果[11] invokeGuardedCallback                           <- 第三步[12] invokeGuardedCallbackImpl$1[13] dispatchEvent[14] func=commitLayoutEffects[11] markCommitStopped

我们看到 commitRoot 总共包含了三个步骤:

  • commitBeforeMutationEffects:将 div#root 置空
  • commitMutationEffects:将 #text 实际写入 DOM 中
  • commitLayoutEffects:当前示例,这一块没有特殊要说明的事情

commit 阶段markCommitStartedmarkCommitStopped 标记了开始和结束。

值得注意的是,commit 阶段 第三步 commitLayoutEffects 之前,
React 会将 FiberRootNode 的 current 属性指向创建好了 Fiber Tree。
(总共有两个 Fiber Tree,组件加载过程只创建一个)

如图所示,



参考

React 初窥门径(四):React 组件的加载过程(render 阶段)
VSCode: CodeTour
github: thzt/react-tour
4.1.1 组件加载过程:函数组件(全流程)

最后编辑于:2025-02-24 21:39:58


喜欢的朋友记得点赞、收藏、关注哦!!!


http://www.ppmy.cn/server/173916.html

相关文章

【HarmonyOS Next】鸿蒙应用故障处理思路详解

【HarmonyOS Next】鸿蒙应用崩溃处理思路详解 一、崩溃问题发现后定位 1. 崩溃现象&#xff1a; 常见的崩溃问题表现为&#xff0c;应用操作后白屏闪退&#xff0c;或者应用显示无响应卡死。 2.定位问题&#xff1a; 发现崩溃后&#xff0c;我们首先需要了解复现步骤&#x…

信息安全基石:深入解析CIA三元组(机密性、完整性、可用性)

1. 什么是CIA三元组&#xff1f; **CIA三元组&#xff08;CIA Triad&#xff09;**是信息安全领域的核心模型&#xff0c;定义了信息保护的三大核心目标&#xff1a; Confidentiality&#xff08;机密性&#xff09; Integrity&#xff08;完整性&#xff09; Availability&…

51单片机Proteus仿真速成教程——P1-软件与配置+Proteus绘制51单片机最小系统+新建程序模版

前言&#xff1a;本文主要围绕 51 单片机最小系统的绘制及程序模板创建展开。首先介绍了使用 Proteus 绘制 51 单片机最小系统的详细步骤&#xff0c;包括软件安装获取途径、工程创建、器件添加&#xff08;如单片机 AT89C51、晶振、电容、电阻、按键等&#xff09;、外围电路&…

逐梦DBA:MySQL目录结构与源码

一、主要目录结构 二、源码 首先&#xff0c;你要进入 MySQL下载界面。 这里你不要选择用默认的“Microsoft Windows”&#xff0c;而是要通过下拉栏&#xff0c;找到“Source Code”&#xff0c;在下面的操作系统版本里面&#xff0c; 选择 Windows&#xff08;Architecture …

【Transformer优化】Transformer的局限在哪?

自2017年Transformer横空出世以来&#xff0c;它几乎重写了自然语言处理的规则。但当我们在享受其惊人的并行计算能力和表征能力时&#xff0c;是否真正理解了它的局限性&#xff1f;本文将深入探讨在复杂度之外被忽视的五大核心缺陷&#xff0c;并试图在数学维度揭示其本质。 …

Android 源码下载以及编译指南

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、下载AOSP前的准备二、国内网络下 clone 清华大学开源软件镜像三、编写Python脚本&#xff0c;开始下载android 源码四、源码下载工具包五、编译 一…

【STM32MP157系统移植】2.烧录TF-A到EMMC

目录 准备烧录文件 tf-a-stm32mp157d-atk-serialboot.stm32 u-boot.stm32 tf-a-stm32mp157d-atk-trusted.stm32 .tsv文件 .tsv语法 Opt域 Id域 Id范围&#xff1a; Id含义&#xff1a; Name域 Type域 Device域 Offset域 Binary域 烧录文件 查看TF-A烧录时间 …

UV,纹理,材质,对象

先上代码&#xff1a; Shader "Unlit/MyFirstShder" {Properties{_MainTex ("Texture", 2D) "white" {}}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex …