DOM diff 算法

201 阅读1分钟

什么是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>

参考文章: