likes
comments
collection
share

🔥🔥🔥7 张图学会两种 React Diff 算法

作者站长头像
站长
· 阅读数 2

一、为什么要有 Diff,什么是 Diff 算法?

在讨论 React 的时候,我们经常会提到 Diff 算法的概念。那么,为什么我们需要 Diff 算法,它又是如何工作的呢?

在 React 中,开发者通过编写 JSX 代码来描述用户界面。React 将这些 JSX 代码转换成虚拟 DOM,然后根据虚拟 DOM 来构建真实的 DOM 结构。当应用的状态发生变化时,React 会生成一棵新的虚拟 DOM 树,接着需要决定如何高效地将这些变化反映到真实的 DOM 上。

这就是 Diff 算法发挥作用的地方。Diff 算法负责比较新旧虚拟 DOM 树的差异,并计算出最小的更新操作集合来使真实 DOM 与最新的虚拟 DOM 树保持同步。这个过程大大减少了不必要的 DOM 操作,从而提高了应用的性能和响应速度。

🔥🔥🔥7 张图学会两种 React  Diff 算法

React Diff 算法,在 React16 版本的时候发生过一次代,我们就分开来看下:

二、 React 16 之前

在 React 16 之前,直接递归对比两棵虚拟 DOM ,遵循两个原则:

2.1 同级比较

React 仅对同一层级的元素进行比较。

🔥🔥🔥7 张图学会两种 React  Diff 算法

同级比较,也意味着在跨层级移动元素的情况下,React 无法识别并复用这些元素。如下图 C、E、F,只能删掉再重新创建。

🔥🔥🔥7 张图学会两种 React  Diff 算法

2.2 先复用,再增删

对于同一级的元素,先复用,再增删。如下图,A、B 直接复用,D 移动一下位置, 然后 C 删掉,X、Y 新增。

🔥🔥🔥7 张图学会两种 React  Diff 算法

三、React 16——fiber

3.1对比 DOM 树的问题

React 16 以前递归对比虚拟 DOM 树的方案有一个明显的问题:阻塞主线程。旧的 React 架构中,Diff 算法和组件更新都是同步执行的。这意味着一旦更新开始,React 会一直占用主线程直到整个更新过程完成。在这期间,浏览器无法响应用户操作,导致界面卡顿,尤其是在执行大规模的 DOM 更新时。

3.2 fiber 简介

🔥🔥🔥7 张图学会两种 React  Diff 算法

React 16 为了优化性能,会先把虚拟 DOM 树转换成 Fiber,也就是从树转换成链表,再基于 Fiber 进行渲染。这个过程分成两个阶段:

  1. reconcile(可中断) :从虚拟 DOM 转换成 Fiber,并给需要操作的节点打上标记。
  2. commit(不可中断) :对有标记的 Fiber 节点进行操作。

Fiber架构通过将渲染工作划分为小的、可管理的单元,使得React能够更好地利用浏览器的主线程,并提供更流畅的用户体验。

3.3 建立 Fiber

第一次渲染不需要 Diff,直接将虚拟 Dom 转为 Fiber。

🔥🔥🔥7 张图学会两种 React  Diff 算法

3.4 更新 Fiber

再次渲染的时候,就需要更新 Fiber 了。这一步的关键是:尽可能复用,尽可能复用旧的 Fiber,来生成本次的 Fiber。

🔥🔥🔥7 张图学会两种 React  Diff 算法

具体的实现方法为两次遍历

第一次遍历: 第一次遍,复用‘位置和内容都相同’的结点。 方法是对比虚拟 DOM 和旧的 Fiber,如果可以复用就继续处理下一个节点,否则就结束遍历。 如上图,相比初始的Fiber,A、B、C 都是完全没变的,直接复用,再往下走原本是 E,但现在变成了 D,发现不能复用,直接返回。

第二次遍历: 第二次遍历,把剩下的内容填上。方法是先把剩余的旧 Fiber 结点做成一个 Map,然后遍历新 DOM 树,构建新 Fiber 的时候查查 Map,能复用就复用,用不了就新建。如上图,构建 D、F、H 的时候发现旧 Fiber 里有,那么可以拿过来复用,M 以前没有,那就新建一个。

总结

React 16 之前的 Diff 算法,是直接对比两棵虚拟 DOM 树,遵循同级比较、先复用再增删的原则,这种方法的问题是做 Diff 的时候会阻塞主线程,造成卡顿。

React 16 引入了 Fiber 概念,用两次遍历来更新 Fiber 链表,基于链表的特性,可以把 Diff 算法拆分为可分割的小块,这样就能保证主线程的运行不会被长时间阻塞,从而提高应用的性能和响应性。

最后提醒一点,别忘给每个元素分配一个唯一的 key 值,不然前面说的都不成立。

参考

vue3js.cn/interview/R… Tree 对比讲的很好。 www.51cto.com/article/716… Fiber 讲的很好。