React 的 diffing 算法

参考资料

协调 - React 中文文档

一、为什么需要 diffing 算法?

在某一时间节点调用 Reactrender() 方法,会创建一棵由 React 元素组成的树。在下一次 stateprops 更新时,相同的 render() 方法会返回一棵不同的树。React 需要基于这两棵树之间的差别来判断如何有效率的更新 UI 以保证当前 UI 与最新的树保持同步。

这个算法问题有一些通用的解决方案,即生成将一棵树转换成另一棵树的最小操作数。 然而,即使在最前沿的算法中,该算法的复杂程度为 O(n 3 ),其中 n 是树中元素的数量。

如果在 React 中使用了该算法,那么展示 1000 个元素所需要执行的计算量将在 十亿 的量级范围。这个开销实在是太过高昂。于是 React 在以下两个假设的基础之上提出了一套 O(n) 的启发式算法:

二、diffing 算法的复杂程度为?

O(n)

三、能做到如此低的算法复杂程度的两个假设基础

  1. 两个不同类型的元素会产生出不同的树;
  2. 开发者可以通过 keyprop 来暗示哪些子元素在不同的渲染下能保持稳定;

在实践中,我们发现以上假设在几乎所有实用的场景下都成立。

四、diffing 算法具体对比

总结:

  1. 对比不同类型的普通元素:当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树。
  2. 对比同一类型的普通元素:① 元素的属性改变时,React 会保留 DOM 节点,仅比对及更新有改变的属性。② 特殊的 style 属性改变时,React 仅更新有所更变的 style 里的属性。
  3. 对比同一类型的组件元素:不改变组件的 state;更新组件的 props;调用实例的相关方法;递归新旧结果。
  4. 对子节点进行递归:① 在子元素列表末尾新增元素时,更新开销比较小,只新增末尾元素。② 将新增元素插入到表头,那么更新开销会比较大,会重建每一个子元素。

1. 对比不同类型的元素

当根节点为不同类型的元素时,React 会拆卸原有的树并且建立起新的树。举个例子,当一个元素从 变成 ,从

变成 ,或从

你可能感兴趣的:(React 的 diffing 算法)