教程前端文档【免费下载链接】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),仅供参考