Under-the-hood-ReactJS 第 0 部分:从 ReactDOM.render 到组件实例化——挂载流程起点全解析
教程前端文档【免费下载链接】Under-the-hood-ReactJSEntire React code base explanation by visual block schemes (Stack version)项目地址https://gitcode.com/gh_mirrors/un/Under-the-hood-ReactJS点击查看免费下载导读本篇是《Under-the-hood-ReactJS》React 源码可视化块状流程解读系列中 Stack 协调器部分的第 0 部分深度解析。文章围绕 React v15.4.2 的ReactDOM.render调用链路展开厘清JSX 到 React 元素的转换、ReactMount模块的挂载职责、TopLevelWrapper的实例化顺序以及虚拟 DOM 背后真实的内部组件类型ReactCompositeComponent、ReactDOMComponent、ReactDOMTextComponent等核心概念。读完后你将能准确回答调用ReactDOM.render之后的第一秒发生了什么并掌握如何沿着ReactElement.js、ReactMount.js等源码路径自行验证每一步为后续学习事务与批量更新第 1 部分打下坚实基础。1. 本部分在全系列中的位置与阅读方式本仓库以两套协调器为主线《Under-the-hood-ReactJS》Stack 版React v15.4.2与 Fiber 版React v16本部分属于Stack 协调器的讲解体系。整个挂载/更新流程被作者拆解为 15 个部分每一部分对应一张可点击放大的可视化流程图本部分Part 0正是整个调用链的第一站。总览流程图位于 stack/images/intro/all-page-stack-reconciler-25-scale.svg同名 JPG 预览见 all-page-stack-reconciler-25-scale.jpg中文版章节目录见 stack/languages/chinese/book/README.md。该系列在 README.md 中明确说明本系列基于React v15.4.2解释旧版 ReactStack 协调器的工作原理。因此文中所引用的src\isomorphic\classic\element\ReactElement.js、src\renderers\dom\client\ReactMount.js等路径均为 React 官方源码相对路径指向的是 React v15.4.2 的代码结构而非本仓库内文件——本仓库只存放图文解析。阅读建议每张流程图可点击在新标签页打开并缩放查看建议将文章与对应流程图分别放在两个窗口标签页中对照阅读。2. 入口点ReactDOM.render 与 JSX 到 React 元素2.1 一切从这里开始ReactDOM.render是整个应用的渲染入口我们的应用程序正是从这里开始被渲染到 DOM 中。为便于调试作者在系列介绍部分创建了一个简单的ExampleApplication /组件作为调试目标完整代码见 stack/languages/chinese/book/Intro.md其核心结构如下class ChildCmp extends React.Component { render() { return div {this.props.childMessage} /div } } class ExampleApplication extends React.Component { constructor(props) { super(props); this.state {message: no message}; } componentWillMount() { /* ... */ } componentDidMount() { /* setTimeout(() { this.setState({ message: timeout state message }); }, 1000); */ } shouldComponentUpdate(nextProps, nextState, nextContext) { return true; } componentDidUpdate(prevProps, prevState, prevContext) { /* ... */ } componentWillReceiveProps(nextProps) { /* ... */ } componentWillUnmount() { /* ... */ } onClickHandler() { /* this.setState({ message: click state message }); */ } render() { return div button onClick{this.onClickHandler.bind(this)} set state button /button ChildCmp childMessage{this.state.message} / And some text as well! /div } } ReactDOM.render( ExampleApplication hello{world} /, document.getElementById(container), function() {} );2.2 第一步JSX 被转换成 React 元素Element调用ReactDOM.render后发生的第一件事是JSX 会被转换成 React 元素Element。React 元素是简单、直白的普通对象具有简单的结构它们仅仅展示从本组件渲染中返回的内容除此之外没有别的职责。在 React v15 中JSX 语法经编译后会变成React.createElement(type, props, ...children)的调用最终产出的元素对象主要包含以下字段字段含义type由 JSX 描述的标记对象可以是组件类如ExampleApplication也可以是 HTML 标签的字符串如buttonprops从父组件传入的属性集合含childrenkey用于列表 diff 时识别项的唯一标识ref用于在代码中访问组件实例或真实 DOM 节点另外在 React 组件创建过程中它还会将defaultProps与props合并如果显式声明了defaultProps并验证propTypes。也就是说元素对象的产出并不是直通的中间经过了默认属性合并与类型校验这两道关卡。该逻辑的实现细节可参考源码React v15.4.2 仓库路径src\isomorphic\classic\element\ReactElement.js。如需在本系列中对比查看作者对该文件的解读脉络可回到 介绍章节。本部分对应的整体流程图如下图 0-0即 Part 0 的完整调用链3. ReactMount挂载逻辑的真正归属3.1 ReactDOM 只是一个轻量接口在流程图上你可以看到一个名为ReactMount01的模块它包含组件挂载的全部逻辑。实际上ReactDOM本身没有任何逻辑它只是一个与ReactMount配合使用的接口。所以当你调用ReactDOM.render时真正执行的是ReactMount.render。那挂载mounting究竟指的是什么源码注释给出了权威定义挂载是初始化 React 组件的过程。该过程通过创建组件所代表的 DOM 元素并将它们插入到提供的container中来实现。3.2 挂载的实质高层描述 → 低层数据用更通俗的语言来理解挂载过程可以想象成下面的转换图 0-1 / 图 0-2JSX 到 HTMLReact 需要将你的组件描述转换为 HTML以将其放入 DOM 中。要做到这一点它必须处理所有的属性、事件监听、内嵌组件和组件逻辑把高阶描述组件转换成真正可以放进网页的低阶数据HTML。这就是挂载过程的实质。与挂载密切相关的另一张细化图小尺寸版可查看 mounting-scheme-1-small.svg它更精简地展示了组件描述 → 真实 HTML的对应关系。3.3 有趣的事实滚动监听与重排优化02在探索挂载流程的过程中作者插入了一个有趣的事实在第一次渲染根组件时React 会初始化滚动监听并缓存滚动值以便应用程序代码可以访问它们而不触发重排reflow。原因是由于浏览器渲染机制的不同一些 DOM 值不是静态的每次在代码中使用它们时都会被重新计算这显然会影响性能。实际上这主要影响的是不支持pageX和pageY的旧版浏览器React 试图对这种情况做优化。这个小例子说明制作一个运行快速的工具需要用到很多底层技术滚动值的缓存就是其中一例。4. 实例化 React 组件TopLevelWrapper 才是第一个实例4.1 流程图03处实例化的并不是我们的组件回到流程图在图中03处标明创建实例。你可能会以为这里创建的是ExampleApplication /的实例但实际上为时过早——此处实例化的是TopLevelWrapper一个 React 内部的类。React 总是从TopLevelWrapper开始渲染一棵组件树。它几乎是一个空的包装器其render方法组件的 render随后将返回ExampleApplication /// src\renderers\dom\client\ReactMount.js#277 TopLevelWrapper.prototype.render function () { return this.props.child; };也就是说目前被创建的只有TopLevelWrapper真正的ExampleApplication实例要在后续的挂载递归中才会被创建。4.2 三种内部组件类型与虚拟 DOM请观察下面的流程图图 0-3JSX 到虚拟 DOM可以看到图中分为三个部分JSX 会被转换成 React 内部三种组件类型中的一种ReactCompositeComponent—— 代表我们自定义的组件如ExampleApplicationReactDOMComponent—— 代表 HTML 标签如div、buttonReactDOMTextComponent—— 代表文本节点。其中ReactDOMTextComponent在本书中被略过重点讲解前两类。那么内部组件与虚拟 DOM是什么关系虚拟 DOM 是一种 DOM 的表现形式React 用虚拟 DOM 进行组件差异计算diff等过程过程中无需直接操作真实 DOM这使得 React 在更新视图时更快。但注意一个容易被忽略的事实在 React 的源码中没有名为 Virtual DOM 的文件或类。虚拟 DOM 只是一个概念一种操作真实 DOM 的方法论。因此作者明确表达了自己的观点虚拟 DOM 不是单个 React 组件而是这三个内部组件类的集合——ReactCompositeComponent、ReactDOMComponent和ReactDOMTextComponent。后续章节第 2 部分及以后会进一步解释为什么这种划分成立。4.3 有趣的事实DOM 嵌套验证validateDOMNesting在探索中还值得注意一个验证环节几乎每次内嵌组件渲染时都会被一个专门用于 HTML 验证的validateDOMNesting模块验证。DOM 内嵌验证指的是子标签 - 父标签的标签层级验证。例如如果父标签是select那么子标签应该是以下之一option、optgroup或者#text。这些规则定义在 HTML 规范https://html.spec.whatwg.org/multipage/syntax.html中。你可能已经见过这个模块的工作方式它通常像这样报错div cannot appear as a descendant of pdiv不能作为p的后代出现5. 小结Part 0 的要点提炼让我们回顾一下本部分的内容。先看完整流程图删除掉多余的不太重要的部分变成 图 0-4简述版再调整间距和对齐得到 图 0-5调整版。实际上这就是本部分发生的所有事情。由此我们可以提取出第 0 部分的核心要点并将其用于最终的mounting挂载流程中一句话概括本部分调用ReactDOM.render→ JSX 被转换为 React 元素 → 经由ReactMount.render进入挂载流程 → 在事务Transaction的保护下实例化TopLevelWrapper→ 组件树被递归转换为三种内部组件类型复合组件、DOM 组件、文本组件并最终产出可插入文档的 HTML。不过请注意挂载方法真正执行时是被包裹在事务中的——在 mount 之后React 需要检查已挂载的组件对环境产生的影响并执行相应更新。这正是第 1 部分事务与批量更新要深入讲解的内容那里会介绍ReactUpdates模块、ReactDefaultBatchingStrategyTransaction及其包装器FLUSH_BATCHED_UPDATES、RESET_BATCHED_UPDATES。6. 系列导航 上一页介绍含示例应用与总览流程图下一页第 1 部分 事务 Transaction中文版首页章节总目录仓库根 README含两套协调器结构总览赞分享教程前端文档【免费下载链接】Under-the-hood-ReactJSEntire React code base explanation by visual block schemes (Stack version)项目地址https://gitcode.com/gh_mirrors/un/Under-the-hood-ReactJS点击查看免费下载相关推荐Under-the-hood-ReactJS 源码解析从 ReactDOM.render 到挂载的完整调用链Stack Reconciler 第 0 部分Under the hood ReactJS 源码解析从 ReactDOM.render 到挂载的完整调用链Stack Reconciler 第 0 部分教程前端文档Under-the-hood-ReactJS 源码解析Part 0从 ReactDOM.render 到挂载JSX 如何一步步变成真实 DOMUnder the hood ReactJS 源码解析Part 0从 ReactDOM.render 到挂载JSX 如何一步步变成真实 DOM 本文聚焦教程前端文档3种方式搞定One API版本升级从手动到智能的完整方案3种方式搞定One API版本升级从手动到智能的完整方案 你是否还在为AI接口管理系统的版本更新而烦恼每次升级都要备份数据、替换文件、重启服务还要担心兼容后端API网关LLM 网关大模型上一篇从混乱到整洁dupeGuru如何让文件管理变得简单高效下一篇CANN SIMT-API类型转换函数创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Harmony 入门指南:基于 CIL 的 .NET/Mono 运行时方法修补原理与 Hello World 实战

Harmony 入门指南:基于 CIL 的 .NET/Mono 运行时方法修补原理与 Hello World 实战

开发工具 【免费下载链接】Harmony A library for patching, replacing and decorating .NET and Mono methods during runtime 项目地址: https://gitcode.com/gh_mirrors/ha/Harmony 点击查看 免费下载 本篇技术指南围绕开源仓库 Harmony 的官方入门文档 intro.m…

2026/10/7 9:36:25 阅读更多 →
Zabbix 模板实战:通过 SNMP 监控 Ciena 3906 智能 CPE 设备

Zabbix 模板实战:通过 SNMP 监控 Ciena 3906 智能 CPE 设备

指标监控可观测性告警运维 【免费下载链接】zabbix Real-time monitoring of IT components and services, such as networks, servers, VMs, applications and the cloud. 项目地址: https://gitcode.com/gh_mirrors/zabbix2/zabbix 点击查看 免费下载 导读 本文…

2026/10/7 9:36:25 阅读更多 →
Wand 修改器本地补丁 3 步跑通:WeMod 高级功能免费解锁 + 手机远程面板

Wand 修改器本地补丁 3 步跑通:WeMod 高级功能免费解锁 + 手机远程面板

Wand 修改器本地补丁 3 步跑通:WeMod 高级功能免费解锁 手机远程面板 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer 是…

2026/10/7 9:35:24 阅读更多 →

最新新闻

gh0st 3.6远控源码剖析:编译、协议与加密全解读

gh0st 3.6远控源码剖析:编译、协议与加密全解读

简介:Gh0st 3.6 红狼官方发布的远程控制源码包,定位为可编译的完整工程,面向具备一定编程基础的系统管理员、安全研究人员和网络编程学习者,用于深入理解远程管理工具的内部实现。压缩包整体约909KB,体积紧凑&#xff…

2026/10/7 10:39:22 阅读更多 →
RFSoC RF Data Converter IP时钟树与PLL配置实战指南

RFSoC RF Data Converter IP时钟树与PLL配置实战指南

1. 为什么RFSoC的时钟树值得单独拎出来讲 Zynq UltraScale RFSoC 这颗芯片最吸引人的地方,就是把多路吉采样率 ADC/DAC 和可编程逻辑塞进了同一块硅片里。但真正让硬件工程师头疼的,往往不是逻辑资源够不够,而是 RF Data Converter IP 里那一…

2026/10/7 10:39:22 阅读更多 →
SpringBoot+Vue+MySQL宠物商城源码从环境配置到跑通全流程实操指南

SpringBoot+Vue+MySQL宠物商城源码从环境配置到跑通全流程实操指南

手里有一套标着"可直接运行"的SpringBootVueMySQL宠物商城源码,却死活跑不起来?这套宠物商城网站信息管理系统源码,我从拿到项目、搭建环境、改配置到最终跑通上线,前后折腾了两天时间。今天不吹不黑,把这套…

2026/10/7 10:39:22 阅读更多 →
PCB工程输出实战:Gerber、钢网与贴片坐标文件生成检查指南

PCB工程输出实战:Gerber、钢网与贴片坐标文件生成检查指南

1. PCB工程输出到底在输出什么画完PCB,点下保存,事情才做了一半。真正决定这块板子能不能顺利投产、贴片良率能不能稳住、工厂会不会半夜打电话让你改文件的,是最后那一步——工程输出。我见过太多设计本身没大毛病、却在输出环节翻车的案例&…

2026/10/7 10:39:22 阅读更多 →
MTK Neurapilot高级部署:APU硬件语义级推理优化实战

MTK Neurapilot高级部署:APU硬件语义级推理优化实战

1. 项目概述:这不是一个“装完就能跑”的SDK,而是一套需要深度理解硬件语义的推理引擎调度系统 “大模型推理-MTK Neurapilot SDK高级功能解析与实战配置指南”这个标题里藏着三个关键信号:第一,“大模型推理”不是指跑个BERT或Ti…

2026/10/7 10:39:22 阅读更多 →
Git提交时间修改实战:从amend到filter-repo的完整指南

Git提交时间修改实战:从amend到filter-repo的完整指南

1. 先说清楚:“Git 推送时间”到底指什么“Git推送时间修改”,第一次听到这个需求时,我第一反应是:Git的push动作本身并没有可修改的时间戳。很多人搜索这个关键词,实际想改的是提交(commit)里的…

2026/10/7 10:38:21 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:29:10 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 8:21:32 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 4:21:51 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 1:18:13 阅读更多 →