React 从组件到最终呈现是如何运作的?

360 阅读3分钟

前言

React 中,理解 React 整个运作流程非常重要。 在 React 中,我们写的组件会经历从 组件实例 通过 React.createElement() 创建 React组件DOM 组件(HTML),最终呈现到用户的屏幕上。可是在React组件 到最终呈现在用户的屏幕上,这期间的整个流程是怎么样的?

image.png

这其中的整个运作的流程可以分成四个步骤:

  1. 触发
  2. 渲染阶段(Render Phase)
  3. 提交阶段(Commit Phase)
  4. 浏览器绘制

触发

触发的条件:

  1. 整个应用程序的 初始渲染
  2. 一个或者多个组件的状态发生改变(我们又称为 重新渲染

👉 渲染并不是立刻生效的! 当你调用 setState 方法时,React 并不会立即重新渲染组件。相反,React 会将渲染操作调度到 JavaScript 引擎有空闲时间的时候执行。这种机制可以避免频繁的渲染操作,从而提高性能。

渲染阶段(Render Phase)

  1. 遍历组件树,获取其所有的需要被重新渲染的组件并渲染他们。
  2. 会根据 React 元素生成树,这个树通常被称为是 虚拟DOM(如图所示)。

image.png

  1. 如果有一个子元素状态变化时,该元素的所有子元素都会被重新渲染(无论子元素有没有改变过)。

image.png

  1. 状态更新后的 虚拟DOM树 将与当前的 Fiber树 保持协调一致,会更新成一个新的 Fiber树

Fiber 树

在渲染阶段提到了 Fiber 树,为什么我们需要 Fiber 树,而不是在状态改变的时候直接更新 DOM 树呢?

当然是因为直接操作 DOM 树 并且 。通过 Fiber 树,我们可以只更新虚拟DOM的一小部分,不需要改动的部分可以进行复用。

Fiber 树的运作

通过 React 元素树(也就是虚拟DOM),在初始渲染的时候创建 Fiber 树。因为 Fiber 树的特性(可变的数据结构),在一开始被创建的时候,Fiber 树就不会被摧毁,同时经历重新渲染也不会重新创建一棵新的 Fiber 树。

因此,Fiber 树也被用于跟踪各个组件的状态(使用过的hooks,props,当前状态,effects等)。他们都会被存储在 Fiber 的内部。

image.png

Fiber 树的结构虚拟 DOM 有着差异,Fiber 树采用链表的结构,而每一个节点也被称为 Fiber。

Fiber 树的优势
  • 增量渲染:Fiber 允许 React 将渲染工作拆分成多个小任务,从而可以在主线程空闲时执行这些任务,提高渲染性能。

  • 可中断的渲染:由于渲染工作被拆分成了小任务,React 可以在任务之间中断渲染,以便处理更高优先级的任务(如用户交互)。

  • 优先级调度:Fiber 支持为不同的更新任务分配不同的优先级,使得 React 能够优先处理重要的更新。

渲染阶段的流程图

image.png

提交阶段(Commit Phase)

在提交阶段,是由 ReactDOM 完成的(不是 React

👉 React 写入 DOM:插入、删除和更新(DOM 更新列表被“刷新”到 DOM 中)

👉 提交是同步的:DOM 更新一次性完成,不能被中断。这是必要的,以确保 DOM 不会显示部分结果,始终与状态保持一致

👉 提交阶段完成后,workInProgress Fiber 树将成为下一次渲染周期的 current 树。

浏览器绘制

通过提交阶段的提交,浏览器(或者是移动端等),通过提交对页面进行绘制。

总结

我们可以发现,React 总是不参与跟真实 DOM 的交互,总是在虚拟 DOM 上进行操作。这使得 React对于性能有较好的优化。

最后总结了一份流程图:

image.png