[React 源码] React 18.2 - Visual Dom | JSX | Fiber [1k 字 - 阅读时长2min]

173 阅读3分钟

JSX

JSXECMAScript 的语法拓展,我们可以用 JSX 语法 来更加灵活,自如,声明式的表达 React UI组件JSX最终都会被编译器转译成为 ECMAScript

相信这也是大家喜欢 React 的原因。

旧转换

React.createElement("h1", { id: "title", }, "hello"); 

新转换

import { jsx as _jsx } from "react/jsx-runtime";
_jsx("h1", {
  id: "title",
  children: "hello"
}, "title");

Visual Dom

Visual Dom 是一个普通的 JavaScript 对象。Visual Dom 出现主要是用来解决频繁操作真实 DOM, 从而在写法上,性能上,抽象表现上带来的一系列问题。

有了 Visual Dom 之后,有以下几个优点:

  1. 跨平台 -- Visual Dom 是对 UI 及其交互 的一层抽象描述,不像 DOM 一样和平台强相关。所以可以让这层抽象描述可以用在 Android、iOS、VR

  2. 增量更新 -- 可以实现精准的定量更新,通过 Diff 算法,尽可能的复用节点,从而尽可能少的操作/改变真实 Dom

  3. 处理兼容性 -- 处理浏览器的版本对 API 的兼容/polyfill 和支持。

  4. 安全性 -- Visual Dom 内容经过 XSS 处理,可以防范 XSS 攻击。

  5. 轻量级 -- 虚拟 DOM 属性,继承的层级 都比 原生少很多。

Visual Dom 缺点 :

  • 虚拟 DOM 的创建和消费需要消耗额外的内存。
  • 虚拟 DOM 首次渲染其实并不一定会更快。

Fiber

为什么会出现 Fiber

Fiber 之前的 React 的工作架构,就是一气呵成,从根节点出发,遍历整个应用程序,独占浏览器的线程资源。随着前端应用程序的规模不断扩大,之前的工作架构遇到了性能问题,或者说是性能瓶颈。性能瓶颈产生的原因是:

主流屏幕的刷新率为 60HZ (1s 刷新 60次), 也就是浏览器每刷新一帧,花费时间为 16.8ms, 为了保证浏览器的每一帧都能够流畅刷新,那么必须保证浏览器 1 帧的时间不能超过 16.8ms, 超过了这个时间,浏览器不能流畅的刷新下一帧,浏览器就会卡帧,丢帧,用户会感觉到明显卡顿和响应丢失。

所以对于之前的 React 工作架构来说,执行 React 代码时,会一直独占浏览器的线程资源,会导致 浏览器 1 帧的时间超过 16.8ms, 导致卡帧,掉帧,丢顿, 并且 Javascript 引擎和页面渲染引擎在同一个渲染线程, GUI 渲染和 Javascript 执行两者是互斥的。 如果某个任务执行时间过长,浏览器会推迟渲染。除此之外,浏览器线程资源一直被 JavaScript 独占,用户的响应事件,动画会丢失,卡顿。

所以 Fiber 的出现,就是为了解决上述问题。

Fiber 是什么?

Fiber 本质就是一个普通的 JavaScript 对象,也是 React 的最小执行单元。Fiber架构就是由 一个个的 Fiber 对象组成的数据结构。

image.png

Fiber 能做什么?

通过Fiber架构/数据结构或者说 Fiber 的出现,React 的协调过程由一气呵成变成可被中断式调度。React 可以适时地让出浏览器线程资源,让浏览器及时地响应用户的交互,渲染 Dom,执行动画。每次执行完一个 Fiber 执行单元, React 就会检查浏览器的 1 帧 现在还剩多少时间,如果没有时间就将控制权让出去。

Fiber 的缺点?

最小执行单元是一个 Fiber,如果单个 Fiber 的计算太复杂,还是会大量占据浏览器一帧的时间。尽管有高优先级打断低优先级,解决饥饿问题等策略。但是硬件设备的瓶颈,软件层面只能是尽可能的优化,尽可能的缓解。