ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Under-the-hood-ReactJS 入门导读:以流程图驱动 React Stack 协调器源码调试

Under-the-hood-ReactJS 入门导读:以流程图驱动 React Stack 协调器源码调试 教程前端文档【免费下载链接】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》仓库中文版的开篇导读主题是带你理解 ReactStack 版本对应 React v15.4.2内部架构的两条核心主线——组件的挂载mount与更新update。它向你展示如何借助作者逐行调试生成的“整体流程图”快速建立全局认知并给出一个可复现的最小调试示例让你从ReactDOM.render与component.setState这两个入口出发沿着 15 个章节逐步深入源码。读完本文你将掌握流程图的阅读方法模块颜色图例、多平台依赖关系、搭建本地调试代码的方法以及理解 React 如何把 JSX 一步步转化为真实 DOM 的整体框架。本仓库的所有流程图均可点击后在新标签页打开并放大阅读。建议将文章与当前讲解的流程图分别放在两个窗口标签页中便于对照文本与调用链。仓库说明整个 Stack 协调器流程图被划分为 15 个部分Part 0 ~ Part 14本导读是这趟源码之旅的起点目录见 README.md。整体流程图两条主流程、一次全局俯瞰仓库在 stack/images/intro/all-page-stack-reconciler-25-scale.svg 提供了一张覆盖全部源码调用关系的总览图缩略图见同目录的all-page-stack-reconciler-25-scale.jpg。先花点时间通览整张图——它看起来非常复杂但实际上只描述了两个流程挂载mount把组件树渲染成真实 DOM 并插入文档更新update响应setState等变更重新渲染受影响的部分。图例刻意跳过了卸载unmount因为卸载本质上是“反向挂载”删除它可以让流程图大幅简化。作者明确说明这张图并非与源码 100% 对应它只描述架构的主要部分大约覆盖源码的 60%另外约 40% 的代码因不具备视觉价值而被省略。因此阅读时应把流程图当作架构索引而非逐行真相。读懂图中的颜色父模块着色规则乍看之下图中有大量颜色。其实规则很简单每个逻辑项图上的形状都以其父模块的颜色高亮。例如若红色模块 B调用了方法 A那么方法 A也是红色的。由此你可以一眼看出某个方法隶属于哪个模块、被哪条调用链驱动。模块颜色与文件路径的完整图例见 stack/images/intro/modules-src-path.svg其中标注了每个模块对应的源码文件路径例如ReactMount、ReactCompositeComponent、ReactDOMComponent等。将这些模块放入一张图就得到了模块之间的依赖关系图stack/images/intro/files-scheme.svg。多平台支持同一个模块多份实现React 生来就是为多种运行环境设计的移动端ReactNative浏览器ReactDOM服务端渲染ReactART使用 React 绘制矢量图形其它因此实际源码中不少文件比单平台依赖图看起来“更大”——每个平台都有独立实现。完整版多平台依赖关系见 stack/images/intro/modules-per-platform-scheme.svg图中有些项“翻倍”出现正说明它们为每个平台各提供了一份实现。以ReactEventListener为例不同平台的事件监听实现显然不同。这些平台相关的模块需要以某种方式注入当前逻辑流程React 内部确实存在大量此类“注入器”其用法属于标准的组合composition模式。为保持图面简洁作者选择忽略它们。本篇系列选定常规浏览器中的 React DOM作为讲解平台——它是最常用的平台且能完整覆盖 React 的所有架构设计理念。调试示例两个入口、一个最小组件学习框架/库源码的最佳方式就是研读并调试源码。本系列将调试两个核心流程ReactDOM.render—— 对应组件的挂载component.setState—— 对应组件的更新。为此准备一个简单、易调试的最小示例包含一个子组件和一个父组件父组件中预留了几乎全部生命周期钩子与setState触发点默认被注释掉可自行打开用于调试更新流程。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() {} );这段代码刻意保持“小而全”既有组件嵌套ExampleApplication与ChildCmp、属性传递childMessage又保留了生命周期钩子的空实现与两处注释掉的setState触发方式setTimeout定时触发与按钮点击触发。在调试时你可以在这些断点处逐步跟踪挂载与更新两条流程。官方文档中这些生命周期方法分别对应挂载期componentWillMount/componentDidMount、更新期shouldComponentUpdate/componentDidUpdate/componentWillReceiveProps和卸载期componentWillUnmount。两条主流程的源码级预览本导读只给出骨架后续 Part 0 ~ Part 14 将逐块拆解整个流程图。这里先预告几个关键环节便于建立整体心智模型。挂载流程的起点挂载流程从ReactDOM.render进入详见 Part 0JSX 首先被转换为结构简单的React 元素element接着进入ReactMount模块——ReactDOM内部几乎没有逻辑它只是与ReactMount协作的接口调用ReactDOM.render实际等于调用ReactMount.render。挂载的本质是把组件的高层描述组件、属性、事件监听、嵌套逐步降级为低层数据HTML从而插入文档。值得注意的是React 总是从内部类TopLevelWrapper开始渲染组件树其render方法仅返回this.props.child源码见src\renderers\dom\client\ReactMount.js#277。虚拟 DOM 在 React 源码中并没有名为 “Virtual DOM” 的文件或类——它只是一个概念具体由ReactCompositeComponent自定义组件、ReactDOMComponentHTML 标签和ReactDOMTextComponent文本节点三类内部组件承担相关转换见 stack/images/0/jsx-to-vdom.svg。Transaction 与批量更新React 以**批量batch**方式执行更新先收集操作再统一执行从而让前置/后置条件只对整批元素应用一次。支撑这一机制的是Transaction事务模式详见 Part 1每个 wrapper 是一对initialize/close方法事务依次执行initialize缓存返回值→ 事务方法本身 →close。React 内部存在多种事务类例如ReactDefaultBatchingStrategyTransactionwrapper 中的close调用ReactUpdates.flushBatchedUpdates启动对脏组件的校验与重渲染ReactReconcileTransactionwrapper 用于保存选中文本范围、抑制 blur/focus 事件、收集componentDidUpdate回调见 Part 2。事务的其它典型用途还包括在 reconciliation 前后保留输入选区、在重排 DOM 时停用事件系统、在 worker 线程完成 reconciliation 后把 DOM 变更刷回主线程等。组件的实际挂载ReactCompositeComponent.mountComponent是挂载旅程中最重的部分之一详见 Part 3。挂载期间组件实例会被赋予props、context、refs以及updater来自ReactUpdateQueue是后续setState的关键依赖源码见src\renderers\shared\stack\reconciler\ReactCompositeComponent.js#255。随后new ExampleApplication()才真正被创建——这是你的代码首次被 React 生态触碰。接着调用componentWillMount在此调用setState只重算 state 而不会触发 render因为组件尚未挂载再调用render()得到子元素为子元素创建ReactDOMComponent等 VDOM 实例并继续递归挂载。挂载到 HTML 标签层时详见 Part 4若标签是video、form、textarea等“复杂标签”会套用额外 wrapper如ReactDOMSelect、ReactDOMTextarea位于src\renderers\dom\client\wrappers\随后校验内部 props例如dangerouslySetInnerHTML必须形如{__html: ...}最终由document.createElement创建真实 DOM 元素。更新流程的起点setState的触发有两种方式外部事件如鼠标点击或内部代码如setTimeout详见 Part 9。前者经ReactEventListener顶层处理后开启批量更新仅当其enabled时挂载期ReactReconcileTransaction的 wrapper 会暂时禁用它以保证挂载安全后者则在把组件放入dirtyComponents列表前确保事务已开启。两条路径最终汇合为同一套步骤调用setState→ 若事务未开启则开启 → 把受影响的组件加入dirtyComponents→ 关闭事务并调用ReactUpdates.flushBatchedUpdates统一处理。整体示意见 stack/images/9/set-state-update-start.svg。下一站至此我们已经掌握了本系列的全局框架一张总流程图、两类核心流程挂载/更新、一套模块着色规则与多平台依赖视角以及一个可用于调试的最小示例。接下来就可以从ReactDOM.render的入口出发一个部分接一个部分地拆解整张流程图。请继续阅读第 0 部分ReactDOM.render 与挂载起点完整章节目录中文版首页如需对照英文原文或其它语言版本可访问 英文版 Intro 与 韩文版Fiber 版本的内容仍在建设中见 fiber/book/Intro.md。赞分享教程前端文档【免费下载链接】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 中文版导读Stack 协调器 15 部分源码级流程解析Under the hood ReactJS 中文版导读Stack 协调器 15 部分源码级流程解析 本指南基于开源仓库 Under the hood Rea教程前端文档从零读懂 React 源码Under-the-hood-ReactJS 的 Stack Reconciler 全景流程导览从零读懂 React 源码Under the hood ReactJS 的 Stack Reconciler 全景流程导览 本指南是 Under the ho教程前端文档PaddleOCR iOS 端部署实战基于 SwiftUI 与 ONNX Runtime 的检测识别 Demo 全流程指南PaddleOCR iOS 端部署实战基于 SwiftUI 与 ONNX Runtime 的检测识别 Demo 全流程指南 PaddleOCR 在仓库的 de教程前端文档上一篇Lucky DDNS Webhook 实战指南公网 IP 一变手机立刻收到推送下一篇rclone copyurl 命令详解免落盘直传 URL 文件到任意远程存储创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表