-
是什么
DOM diff 就是对比两棵虚拟 DOM 树的算法(废话很重要)。当组件变化时,会 render 出一个新的虚拟 DOM,diff 算法对比新旧虚拟 DOM 之后,得到一个 patch,然后 React 用 patch 来更新真实 DOM。
-
怎么做
-
首先对比两棵树的根节点
- 如果根节点的类型改变了,比如 div 变成了 p,那么直接认为整棵树都变了,不再对比子节点。此时直接删除对应的真实 DOM 树,创建新的真实 DOM 树。
- 如果根节点的类型没变,就看看属性变了没有
-
如果没变,就保留对应的真实节点
-
如果变了,就只更新该节点的属性,不重新创建节点。
a. 更新 style 时,如果多个 css 属性只有一个改变了,那么 React 只更新改变的。
-
-
然后同时遍历两棵树的子节点,每个节点的对比过程同上。
情况一
<ul> <li>A</li> <li>B</li> </ul> <ul> <li>A</li> <li>B</li> <li>C</li> </ul>
React 依次对比 A-A、B-B、空-C,发现 C 是新增的,最终会创建真实 C 节点插入页面。 情况二
<ul> <li>B</li> <li>C</li> </ul> <ul> <li>A</li> <li>B</li> <li>C</li> </ul>
React 对比 B-A,会删除 B 文本新建 A 文本;对比 C-B,会删除 C 文本,新建 B 文本;(注意,并不是边对比边删除新建,而是把操作汇总到 patch 里再进行 DOM 操作。)对比空-C,会新建 C 文本。
你会发现其实只需要创建 A 文本,保留 B 和 C 即可,为什么 React 做不到呢?
因为 React 需要你加 key 才能做到:
<ul> <li key="b">B</li> <li key="c">C</li> </ul> <ul> <li key="a">A</li> <li key="b">B</li> <li key="c">C</li> </ul>
React 先对比 key 发现 key 只新增了一个,于是保留 b 和 c,新建 a。
注意:Vue 的diff算法才是「双端交叉对比」算法
双端交叉对比的 具体的diff分析 canyuegongzi.github.io/web/vue/3.h… juejin.cn/post/697162…
-