返回介绍

开篇

发布于 2025-01-10 12:49:04 字数 2693 浏览 0 评论 0 收藏 0

React 影响着我们工作的方方面面,我们每天都在使用它,只窥其表却难以窥其里。正所谓看不如写,本篇文章的目的就是从原理层面探究 React 是如何工作的。

工具

在写文章之前,为了方便理解,我准备了一个懒人调试仓库 simple_react ,这个仓库将 benchmark 用例(只有两个 ^ ^)和 React 源码共同放在 src 文件夹中,通过 snowpack 进行热更新,可以直接在源码中加入 log 和 debuger 进行调试。当然这里的“源码”并不是真的源码,因为 React 源码中充斥着巨量的 dev 代码和不明确的功能函数,所以我对源码进行了整理,用 typescript 对类型进行了规范,删除了大量和核心流程无关的代码(当然也误删了一些有关的 ^ ^)。

如果你只是希望了解 React 的运行流程而不是写一个可以用的框架的话,那么这个仓库完全可以满足你学习的需要。当然,这个仓库基于 React16.8 ,虽然这个版本并不包括当前的航道模型 Lane 等新特性,但是是我个人认为比较稳定且更适合阅读的一个版本。

(如果希望调试完整的源码,也可以参考 拉取源码 通过 yarn link 来进行 debug)

文章结构

  1. fiber 架构设计及首次渲染流程
  2. 事件委托机制
  3. 状态的更新
  4. 时间片

在了解 React 是如何工作之前,我们应该确保了解几点有关 React 的基础知识。

Why Framework

首先,我们需要知道使用框架对于开发的意义是什么。如果我们还处于远古时期使用纯 JS 的阶段,每次数据的改变都会引发组件的展示状态改变,因此我们需要去手动的操作 DOM 。如果在某一秒内,数据异步的连续改变了几十次,根据展示逻辑我们也需要连续对 DOM 进行几十次修改。频繁的 DOM 操作对网页性能的影响是很大的,当然,创建 DOM 元素和修改 DOM 元素的属性都不过分消耗性能,主要在于每次将新的 DOM 插入 document 都会导致浏览器重新计算布局属性,以及各个视图层、合并、渲染。所以,这样的代码性能是十分低下的。

可以试想这样一个场景。对于一个前端列表组件而言,当存在 3 条数据的时候展示 3 条,当存在 5 条数据的时候展示 5 条。也就是说 UI 的呈现在某种程度上必然会和数据存在某种逻辑关系。如果 JS 能够感知到关键数据的改变,使用一种高效的方式将 DOM 改写成与数据相对应的状态。那么于开发者而言,就可以专注于业务逻辑和数据的改变,工作效率也会大幅提高。

所以, 框架 最核心的功能之一就是 高效地 达成 UI 层和数据层的统一。

React 哲学

React 本身并不是框架, React 只是一个 JavaScript 库,他的作用是通过组件构建用户界面,属于 MVC 应用中的 View 视图层。 React 通过 props 和 state 来简化关键数据的存储,对于一个 react 组件函数而言,在 1 秒内可能被执行很多次。而每一次被执行,数据被注入 JSX , JSX 并不是真实的 DOM ,在 React 中会被转换成 React.createElement(type, props, children) 函数,执行的结果就是 ReactElement 元素 ,也即是 虚拟 DOM ,用来描述在浏览器的某一帧中,组件应该被呈现为什么样子。

Virtual Dom

VirtualDom 并非 React 专属,就像 redux 也可以在非 React 环境下使用一样,它们只是一种设计的思路。

事实上, React 在使用 fiber 架构之前的 Virtual Dom 和 diff 过程要相对直观一些。但是在引入了 fiber 架构之后整个流程变得冗长,如果单纯想了解 VirtualDom 和 diff 过程的原理也可以通过 simple-virtual-dom 这个仓库来学习。

VirtualDom 的本质是利用 JS 变量 对真实 DOM 进行抽象,既然每一次操作 DOM 都可能触发浏览器的重排消耗性能,那么就可以使用 VirtualDom 来缓存当前组件状态,对用户交互和数据的变动进行批次处理,直接计算出每一帧页面应该呈现的最终状态,而这个状态是以 JS 变量 的形式存在于内存中的。所以通过 VirtualDom 既能够保证用户看到的每一帧都响应了数据的变化,又能节约性能保证浏览器不出现卡顿。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文