ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

React Stack Reconciler 挂载流程解析(第 6 部分):mountChildren 与初始子组件挂载全链路

React Stack Reconciler 挂载流程解析(第 6 部分):mountChildren 与初始子组件挂载全链路 教程前端文档【免费下载链接】Under-the-hood-ReactJSEntire React code base explanation by visual block schemes (Stack version)项目地址https://gitcode.com/gh_mirrors/un/Under-the-hood-ReactJS点击查看免费下载React 的挂载mounting并不是只创建根组件就结束真正的重头戏在于把render返回的元素递归地铺开成一棵真实的 DOM 树。本篇基于 Under-the-hood-ReactJS 仓库 Stack 版系列的 Part 6深入剖析子组件挂载的两大步骤this.mountChildren与DOMLazyTree.queueChild、ReactMultiChild/ReactChildReconciler的分工以及完整回顾从ReactCompositeComponent到ReactDOMComponent的递归挂载链路。读完本文你将能清晰回答React 到底如何把一个组件树变成 DOM 树、子组件是按什么规则分派给不同内部组件类这两个核心问题。一、Part 6 在整个挂载流程中的位置在进入子组件挂载之前需要先回顾整个系列的脉络Part 0 讲解了ReactDOM.render入口JSX 被 Babel 解析后通过React.createElement变成 React 元素再被实例化为三种内部组件类型——ReactCompositeComponent自定义组件、ReactDOMComponentHTML 标签、ReactDOMTextComponent文本节点Part 2 引入了ReactReconcileTransaction事务及其三个 wrapper以及ReactReconciler这个中介者模块Part 3 展开了ReactCompositeComponent.mountComponent实例化你的自定义组件、调用生命周期钩子、执行render然后为返回的元素创建ReactDOMComponent实例并继续调用mountComponentPart 4 与 Part 5 分别覆盖了ReactDOMComponent的标签包装、props 校验、document.createElement建真实 DOM 节点以及updateDOMProperties对 props 的 diff 应用。到 Part 6 为止div这个元素本身的挂载已经完成接下来顺理成章的问题就是它的 children 怎么办这正是本篇的核心主题。二、子组件挂载的两个步骤mountChildren 与 queueChild在ReactDOMComponent完成自身挂载后需要继续处理它的子节点。原文明确指出这里包含两个步骤this.mountChildren挂载子组件——真正把每个子元素实例化并挂载这是最有技术含量的一步DOMLazyTree.queueChild连接父子——把挂载好的子节点挂接到父节点上。DOMLazyTree是一个工具类负责维护挂载过程中构建的树形数据结构例如它会让children与node真实 DOM 节点保持关联。之所以叫 Lazy与整个挂载流程先把数据准备好、再一次性插入文档的延迟策略一致——这一点在 Part 7 的parentNode.insertBefore(tree.node)收尾步骤中可以看到最终落地效果。从模块分工上看子组件管理被独立抽成了一个专门的模块ReactMultiChild书中给出的路径为src\renderers\shared\stack\reconciler\ReactMultiChild.js。这个模块的核心职责就是统一处理一个父组件的一批子组件的挂载与后续更新它同时服务于 mount 和 update 两条链路。三、mountChildren 内部的两个主要任务mountChildren方法内部同样包含两个主要任务1. 实例化子组件交给 ReactChildReconciler使用ReactChildReconciler来实例化所有的子组件。这一层负责处理 children 的各种形态数组、单个元素、文本字符串等并把它们统一转换为内部组件实例。React 元素的 key/ref 等元数据也会在这一层被妥善处理为后续的 diff 更新Part 8 之后的更新流程做好准备。2. 挂载子组件实例化完成后逐个调用挂载逻辑。这里的关键点在于挂载流程完全取决于子组件的类型而类型分派规则非常清晰子组件来源实例化的内部组件类对应挂载流程简单 HTML 标签如div、spanReactDOMComponent走 DOM 组件挂载Part 4 / Part 5 的流程自定义组件如ChildCmpReactCompositeComponent走复合组件挂载Part 3 的流程换句话说Part 6 并不是一条全新的代码路径而是一个分叉点它对每个子元素重新进入前面已经讲过的挂载过程。原文用一句非常精炼的话概括了这种递归性——The mounting flow, again, depends on what the child type is.这与 Part 0 里提到的三种内部组件类型是一一对应的JSX → React 元素 →实例化为ReactCompositeComponent/ReactDOMComponent/ReactDOMTextComponent。Part 6 正是这套分类机制在子组件维度上的实际执行。四、整体挂载流程六步回顾为了让读者不被细节淹没Part 6 特意插入了一次One more time的整体回顾用下面这张总图把前面的内容串起来图 4.1 整体挂载方案可点击放大查看细节整个挂载过程可归纳为六个步骤实例化并挂载复合组件React 为你的每个自定义组件创建ReactCompositeComponent实例它管理着componentWillMount等生命周期钩子并挂载它创建自定义组件实例挂载过程中首先实例化你的组件类此时你的constructor会被调用调用 render 产生 React 元素执行render简单例子中返回div由React.createElement创建 React 元素——可以直接调用也可以经由 Babel 解析 JSX 后替换 render 中的标签创建 DOM 组件基于上一步的 element 对象为div创建ReactDOMComponent实例挂载 DOM 组件这一步真正创建 DOM 元素、注册事件监听器等处理初始子组件为 DOM 组件的直接子元素创建实例并挂载。根据每个子元素是自定义组件还是普通 HTML 标签递归回到步骤 1 或步骤 5然后对所有嵌套元素重复这一过程。这套递归逻辑正是挂载一棵树的完整定义先父后子、层层递进直到整棵虚拟 DOM 树都被物化为真实 DOM 节点。原文的评价是 Its pretty straightforward——确实抽象为递归后结构非常清晰。五、componentDidMount 的入队时机六个步骤全部执行完毕挂载基本完成。此时生命周期钩子componentDidMount并不会被立即调用而是入队等待事务的 close 阶段触发。这一点与 Part 2 讲解的ReactReconcileTransaction三个 wrapperSELECTION_RESTORATION、EVENT_SUPPRESSION、ON_DOM_READY_QUEUEING一脉相承componentDidMount的调用回调会被推入transaction.reactMountReady队列只有当事务真正 close即所有挂载副作用都完成、DOM 已就绪时才会被notifyAll触发。完整收尾在 Part 7 中有详细展示先parentNode.insertBefore(tree.node)把节点插入文档再由 close wrapper 通知所有回调。这也解释了为什么componentDidMount里可以安全地访问 DOM——因为此时节点已真正在文档里了。六、从完整流程图到核心价值提炼Part 6 的收尾部分遵循了整个系列的固定节奏从完整流程图逐步做减法提炼出最终可复用的核心价值。图 6.1 Part 6 完整流程可点击放大查看细节首先是简化版本移除冗余且不重要的分支后得到 part-6-A然后是整理间距与对齐的 refactor 版本part-6-B最后沉淀出可并入最终 mounting 总图的核心价值版图 6.2 Part 6 核心价值可点击放大查看细节整个系列的mounting最终方案图mounting-parts-C.svg正是由各 Part 的 C 图拼接而成的——Part 6 贡献的正是子组件挂载 递归回到复合组件/DOM 组件挂载这一段。七、小结与延伸阅读Part 6 的核心结论可以浓缩为一张心智模型挂载子组件 ReactChildReconciler实例化子组件按类型分派为ReactDOMComponent或ReactCompositeComponent 递归挂载 DOMLazyTree.queueChild连接父子。到这里mount 链路还剩最后一步把构建好的树真正插入文档并关闭事务触发componentDidMount——这正是 Part 7 的内容。对于想继续深入本系列的读者推荐按以下顺序阅读Part 5子组件挂载之前父元素自身的updateDOMProperties流程Part 7挂载收尾——DOM 插入与事务 closePart 0JSX 到三种内部组件类型的转换规则理解分派的源头Intro整个 Stack reconciler 总览图与调试用的示例组件代码ExampleApplication/ChildCmp。仓库还提供了中文版 Part 6 与韩文版 Part 6 可供对照阅读。赞分享教程前端文档【免费下载链接】Under-the-hood-ReactJSEntire React code base explanation by visual block schemes (Stack version)项目地址https://gitcode.com/gh_mirrors/un/Under-the-hood-ReactJS点击查看免费下载相关推荐Agentic Awesome Skills 质量标准指南从技能提交到 Validated 徽章的完整验证流程Agentic Awesome Skills 质量标准指南从技能提交到 Validated 徽章的完整验证流程 本篇指南聚焦 Agentic Awesome教程前端文档Under-the-hood ReactJSStack 版Part 6 源码解析初始子元素挂载与递归式 Mounting 全流程Under the hood ReactJSStack 版Part 6 源码解析初始子元素挂载与递归式 Mounting 全流程 本篇文章源自仓库系列文档教程前端文档Under the hood ReactJS用可视化流程图剖析 React Stack reconciler 的挂载与更新机制Under the hood ReactJS用可视化流程图剖析 React Stack reconciler 的挂载与更新机制 本文基于开源仓库 Under教程前端文档上一篇Gumroad 仓库 Sidekiq 实战指南作业去重、批量清理与长任务队列编排下一篇Serena 的 Memories 系统怎么用mem 引用、onboarding 与 memories check创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表