虚拟 DOM

# 虚拟 DOM

原生的 JS DOM 操作非常消耗性能,而 React 把真实原生 JS DOM 转换成了 JavaScript 对象。这就是虚拟 Dom(Virtual Dom)

每次数据更新后,重新计算虚拟 DOM,并和上一次生成的虚拟 DOM 进行对比,对发生变化的部分作批量更新。

<div class="title">
  <span>Hello World</span>
  <ul>
    <li>苹果</li>
    <li>橘子</li>
  </ul>
</div>
const VirtualDom = {
  type: 'div',
  props: { class: 'title' },
  children: [
    {
      type: 'span',
      children: 'Hello World'
    },
    {
      type: 'ul',
      children: [
        { type: 'li', children: '苹果' },
        { type: 'li', children: '橘子' }
      ]
    }
  ]
}

# diff 算法

React 需要同时维护两棵虚拟 DOM 树:一棵表示当前的 DOM 结构,另一棵在 React 状态变更将要重新渲染时生成。React 通过比较这两棵树的差异,决定是否需要修改 DOM 结构,以及如何修改。这种算法称作 diff 算法。

diff 算法大致执行过程:

diff 算法会对新旧两棵树做深度优先遍历,避免对两棵树做完全比较,因此算法复杂度可以达到 O(n)。然后给每个节点生成一个唯一的标志:

# Key 机制

当同一层级的某个节点添加了对于其他同级节点唯一的 key 属性,当它在当前层级的位置发生了变化后。diff 算法通过新旧节点比较后,如果发现了 key 值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。这无疑大大提高了 React 性能和渲染效率。

注意事项:key 值在比较之前都会被执行 toString() 操作,所以尽量不要使用 object 类型的值作为 key,会导致同一层级出现 key 值相同的节点。key 值重复的同一类型的节点或组件很可能出现拷贝重复内部子元素的问题。

LOSER
米津玄師