什么是DOM diff
DOM diff 就是对比两棵虚拟 DOM 树的算法。当组件变化时,会render出一个新的虚拟 DOM,diff 算法对比新旧虚拟 DOM 之后,得到一个patch,然后 React 用 patch 来更新真实 DOM。
DOM diff的过程
首先,对比两棵树的根节点:
- 如果根节点的类型改变,比如 div 变成了 p,那么直接认为整棵树都变了,不再对比子节点,直接删除对应的真实 DOM 树,创建新的真实 DOM 树。
- 如果根节点的类型没变,就看看属性变了没有:
- 如果没变,就保留对应的真实节点。
- 如果变了,就只更新该节点的属性,不重新创建节点。更新 style 时,如果多个 css 属性只有一个改变了,那么 React 只更新改变的。 然后,同时遍历两棵树的子节点,每个节点的对比过程同上。
- 情况一:React 依次对比 A-A、B-B、空-C,发现 C 是新增的,最终会创建真实C节点插入页面。
<ul>
<li>A</li>
<li>B</li>
</ul>
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
- 情况二:React 对比 B-A,会删除 B 文本新建 A 文本; 对比 C-B,会删除 C 文本,新建 B 文本; 对比空-C,会新建 C 文本。
<ul>
<li>B</li>
<li>C</li>
</ul>
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
注意:并不是边对比边删除新建,而是把操作汇总到patch里再进行 DOM 操作。
其实只需要创建 A 文本,保留 B 和 C 即可,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>
参考文章: