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

news2025/4/21 2:19:15

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.coloradmin.cn/o/2311758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java环境部署

java环境部署 一、准备工作 jrejdkeclipse jdk下载&#xff1a;21和1.8-----官网&#xff1a;Oracle&#xff1a;Java 下载 |神谕 该处选择要依据自身的系统类型选择下载 idea的下载安装&#xff1a;IntelliJ IDEA | Other Versions 二、安装 三、环境配置 四、使用 五、i…

100天精通Python(爬虫篇)——第115天:爬虫在线小工具_Curl转python爬虫代码工具(快速构建初始爬虫代码)

文章目录 一、curl是什么&#xff1f;二、爬虫在线小工具&#xff08;牛逼puls&#xff09;三、实战操作 一、curl是什么&#xff1f; 基本概念&#xff1a;curl 支持多种协议&#xff0c;如 HTTP、HTTPS、FTP、SFTP 等&#xff0c;可用于从服务器获取数据或向服务器发送数据&a…

python-leetcode-解决智力问题

2140. 解决智力问题 - 力扣&#xff08;LeetCode&#xff09; 这道题是一个典型的 动态规划&#xff08;Dynamic Programming, DP&#xff09; 问题&#xff0c;可以使用 自底向上 的方式解决。 思路 定义状态&#xff1a; 设 dp[i] 表示从第 i 题开始&#xff0c;能获得的最高…

SpireCV荣获Gitee 最有价值开源项目称号

什么是GVP&#xff1f; GVP全称Gitee Valuable Project&#xff0c;意思为Gitee最有价值开源项目。作为GVP称号的获得者&#xff0c;SpireCV在开源社区中展现出了卓越的实力和影响力&#xff0c;为开源软件的发展和推广做出了积极的贡献。 这一荣誉不仅充分肯定了过去阿木实验…

数据结构基础(一)

文章目录 1 数据结构基础1.1 什么是程序&#xff1f;1.2 数据、数据元素、数据项、数据对象1.3 基本的逻辑结构 2 算法效率2.1 时间复杂度2.1.1 循环执行次数2.1.2 大O(n)表示法 2.2 空间复杂度 1 数据结构基础 1.1 什么是程序&#xff1f; ​ 程序 数据结构 &#xff0b; 算…

⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II

⭐算法OJ⭐N-皇后问题【回溯剪枝】&#xff08;C实现&#xff09;N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…

项目管理工具 Maven

目录 1.Maven的概念 1.1​​​​​什么是Maven 1.2什么是依赖管理 1.3什么是项目构建 1.4Maven的应用场景 1.5为什么使用Maven 1.6Maven模型 2.初识Maven 2.1Maven安装 2.1.1安装准备 2.1.2Maven安装目录分析 2.1.3Maven的环境变量 2.2Maven的第一个项目 2.2.1按照约…

国产编辑器EverEdit - 宏功能介绍

1 宏 1.1 应用场景 宏是一种重复执行简单工作的利器&#xff0c;可以让用户愉快的从繁琐的工作中解放出来&#xff0c;其本质是对键盘和菜单的操作序列的录制&#xff0c;并不会识别文件的内容&#xff0c;属于无差别无脑执行。 特别是对一些有规律的重复按键动作&#xff0c;…

“双碳”背景下,企业应该如何提升能源效率?

在当今竞争激烈的市场环境中&#xff0c;企业不仅需要优化成本&#xff0c;还需积极响应国家的能源政策&#xff0c;减少对环境的影响。提升工业能源效率正是实现这一双重目标的关键。中国近年来大力推进“双碳”目标&#xff08;碳达峰、碳中和&#xff09;&#xff0c;并出台…

文献学习——考虑混合储能系统选择的基于改进蜂群算法的热电联产微网多目标经济优化调度

摘要&#xff1a;在考虑混合储能系统模型选择的基础上&#xff0c;基于改进的人工蜂群算法&#xff08;ABC&#xff09;&#xff0c;建立了冷热电联产微电网经济优化的多目标调度模型。为了对以往研究中的单目标模型进行升级&#xff0c;将模型的优化目标设定为微电网的日发电调…

nnMamba:基于状态空间模型的3D生物医学图像分割、分类和地标检测

摘要 本文提出了一种基于状态空间模型&#xff08;SSMs&#xff09;的创新架构——nnMamba&#xff0c;用于解决3D生物医学图像分割、分类及地标检测任务中的长距离依赖建模难题。nnMamba结合了卷积神经网络&#xff08;CNN&#xff09;的局部特征提取能力与SSMs的全局上下文建…

安科瑞新能源充电桩解决方案:驱动绿色未来,赋能智慧能源

安科瑞顾强 引言 在“双碳”目标与新能源汽车产业高速发展的双重驱动下&#xff0c;充电基础设施正成为能源转型的核心环节。安科瑞电气股份有限公司凭借在电力监控与能效管理领域20余年的技术积淀&#xff0c;推出新一代新能源充电桩解决方案&#xff0c;以智能化、高兼容性…

使用开源OPUS-MT模型进行文本翻译(python)

1. 环境准备 pip install transformers 2. 下载机器翻译模型&#xff1a; 2.1 代码从hugging face平台下载 from transformers import MarianMTModel, MarianTokenizer# 指定模型名称 model_name "Helsinki-NLP/opus-mt-zh-en" # 中译英模型# 下载并保存分词器到…

Elastic如何获取当前系统时间

文章目录 1. 使用 _ingest.timestamp 在 Ingest Pipeline 中获取当前时间2. 使用 Painless Script 获取当前时间3. 使用 now 关键字在查询中获取当前时间4. 使用 date 类型字段的默认值5. 使用 Kibana 的 Dev Tools 查看当前时间6. 使用 date 聚合获取当前时间7. 使用 Elastics…

jenkins配置连接k8s集群

jenkins配置连接k8s集群 前言 我这边jenkins是在一个服务器里面&#xff0c;k8s集群在其他服务器&#xff0c;实现连接 首先jenkins下载有k8s插件 进入配置页面 获取k8s-api-server地址 对应k8s服务器执行 kubectl config view --minify -o jsonpath{.clusters[0].cluste…

如何选择缓存模式?

如何选择缓存模式 当一个系统引入缓存后&#xff0c;最大的挑战之一便是如何确保缓存与后端数据库的一致性。目前&#xff0c;常见的解决方案主要有Cache Aside、Read/Write Throught和Write Back这三种缓存更新策略。 Read/Write Throught策略 读操作方面&#xff0c;如果缓…

网络安全配置截图 网络安全i

网络安全概念及规范 1.网络安全定义 网络安全的概述和发展历史 网络安全 广义的网络安全&#xff1a;Cyber Security&#xff08;网络空间安全&#xff09; 网络空间有独立且相互依存的信息基础设施和网络组成&#xff0c;包括互联网、电信网、计算机系统、嵌入式处理器和控…

k8s概念及k8s集群部署(Centos7)

Centos7部署k8s集群 部署之前&#xff0c;先简单说下k8s是个啥&#xff1a; 一、k8s简介&#xff1a; k8s&#xff0c;全称&#xff1a;kubernetes&#xff0c;它可以看作是一个分布式系统支撑平台。k8s的作用&#xff1a; 1、故障自愈&#xff1a; k8s这个玩意可以监控容器…

Manus详细介绍,Manus核心能力介绍

文章目录 前言Manus产品定位与核心理念:Manus产品特性与未来体验战略:Manus商业价值与创新指标:Manus技术特点与竞争优势:Manus用户反馈与展望:Manus市场竞争优势与团队战略:Manus深度总结与启发: 前言 这是一篇关于Manus智能体产品的用户体验评价报告&#xff0c;主要介绍了M…

Apache XTable:在数据湖仓一体中推进数据互作性

Apache XTable 通过以多种开放表格式提供对数据的访问&#xff0c;在增强互作性方面迈出了一大步。移动数据很困难&#xff0c;在过去&#xff0c;这意味着在为数据湖仓一体选择开放表格式时&#xff0c;您被锁定在该选择中。一个令人兴奋的项目当在数据堆栈的这一层引入互作性…