Vue 虚拟DOM和diff算法原理

4/9/2023 vue

# Vue虚拟dom和diff算法详细原理

# 虚拟DOM

何为虚拟DOM?就是将DOM元素虚拟化,使用数据结构表达出来,保存在内存中。虚拟DOM就是由多个js对象组成的树型结构,每一个DOM节点都是一个js对象,包括标签名、属性、子节点等等。可以轻松的将其创建、更新、销毁,而不涉及真实DOM的操作,可以提高性能。

在Vue中,当数据发生变化时,通过更新前后的虚拟DOM树进行对比,找出变化的部分,最少地更新实际DOM,减少真实DOM操作的次数,从而提高页面渲染的性能和效率。

优势

  • 跨平台
  • 提高DOM操作效率
  • 提升渲染性能

# Diff算法

Diff算法其实就是在vue当中实现前后虚拟DOM树对比,查找差异的过程,让其实现最小量更新

Diff算法的整体策略是深度优先,同层比较,比较的过程中从两边向中间收拢

Diff算法的流程

  • 首先对比根节点
  • 逐层对比子节点
    • 比较子节点类型(标签名+key):
      • 如果类型不同,直接替换整个节点
      • 如果类型相同,继续对比节点的属性和事件
    • 对比子节点列表
      • 使用双指针对比新旧节点列表,查找相同位置的节点
        • 双指针:一个头指针一个尾指针
        • 新老虚拟DOM树都有两个指针,两个列表开始循环(二者头尾指针互相对比),循环停止条件是其中一个列表中的头指针和尾指针重合
      • 如果查找到,节点相同,进行递归对比子节点列表
      • 如果没查找到,节点不同,根据情况进行插入、删除或移动节点操作
  • 处理新增、删除、移动节点
    • 如果新节点列表中存在旧节点列表中没有的节点,执行新增操作。
    • 如果旧节点列表中存在新节点列表中没有的节点,执行删除操作。
    • 如果新旧节点列表中都存在相同的节点,但顺序不同,执行移动节点的操作。
  • 更新节点属性和事件
  • 递归对比子节点

key作用

  • key的作用主要就是为了更高效地更新虚拟DOM,因为它可以精准地找到相同的节点
  • 在源码中对比两个节点是否相同,key是一个必要条件,在渲染列表的时候如果不写key,就会导致频繁更新元素,效率很低
  • 那为什么要避免使用index下标作为key值呢?使用index,key值就不是唯一的了,就会导致一个bug,例如:
    • 旧节点有四个

      index: 0 1 2 3

      ele: li1 li2 li3 li4

      我们现在要在li2和li3中间插入一个li5

      index: 0 1 2 3 4

      ele: li1 li2 li5 li3 li4

      此时key=index,当我们对新旧虚拟DOM进行对比的时候,到第三个元素的时候因为index变化,后面三个元素都会进行变更

    • 那如果我们使用唯一值赋值给key时,以上情况对比的时候就之后更新一个元素

Last Updated: 3/22/2024, 2:53:00 PM
晴天
周杰伦