一个页面就是一个DOM树,当页面发生变化的时候,又会形成另一个DOM树,这两个树要作比较的时候,就用到了Diff算法。
传统的diff算法为O(n^3),相当复杂。
时间复杂度是检测一个算法或者一个性能好坏的重要因数。
其他它没有什么神奇的,只是一个名词而已。
O(n^3) -> O(n^2) -> O(n)
从左到右,时间复杂度越来越小,越小性能越好。
传统的diff算法会比较不同,react的diff算法会先检查结构是否相同,如果不同直接销毁重建。
react将diff算法从O(n^3) 直接变为 O(n), 大大提高了性能。
-
Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。
-
拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。(类似的虚拟DOM节点,不会作比较,而是直接销毁之前的DOM节点,然后添加新DOM节点,省去了两个DOM树的对比,提高了性能)
-
对于同一层级的一组子节点,它们可以通过唯一 id 进行区分。(即map循环要加key这个唯一标识)
基于以上三个前提策略,React 分别对 tree diff、component diff 以及 element diff 进行算法优化,事实也证明这三个前提策略是合理且准确的,它保证了整体界面构建的性能。
-
tree diff
-
component diff
-
element diff
当一个节点从div变成span时,简单的直接删除div节点,并插入一个新的span节点。这符合我们对真实DOM操作的理解。需要注意的是,删除节点意味着彻底销毁该节点,而不是再后续的比较中再去看是否有另外一个节点等同于该删除的节点。如果该删除的节点之下有子节点,那么这些子节点也会被完全删除,它们也不会用于后面的比较。这也是算法复杂能够降低到O(n)的原因。
React的DOM Diff算法实际上只会对树进行逐层比较。
- 两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;
- 对于同一层次的一组子节点,它们可以通过唯一的id进行区分
参考:
http://www.infoq.com/cn/articles/react-dom-diff/
https://zhuanlan.zhihu.com/p/20346379?refer=purerender