大宇宇宇
发布于 2025-09-01 / 21 阅读
1
0

diff算法

在Vue中,diff算法是虚拟DOM(Virtual DOM)的核心优化机制,用于高效比较新旧虚拟DOM树的差异,并最小化真实DOM操作。

1. 核心目标

  • 高效更新:通过对比新旧虚拟DOM,找出最小差异,避免全量渲染,提升性能。

  • 减少DOM操作:真实DOM操作成本高,diff算法只更新必要部分。


2. 核心原则

  • 同层比较(最重要原则):

    • 只比较同一层级的节点,不跨层级比较(如父节点和子节点不直接对比)。

    • 若节点类型不同(如divp),直接销毁旧节点及其子树,创建新节点。


3. 关键流程

(1) 节点比较

  • 类型相同:继续比较子节点和属性。

  • 类型不同:直接替换整个节点(包括子树)。

  • 文本节点:直接比较文本内容,不同则更新。

(2) 子节点优化(重点)

  • 双端比较法(高效处理列表更新):

    • 使用4个指针:oldStartoldEndnewStartnewEnd

    • 依次比较:

      • oldStart vs newStart(头头)

      • oldEnd vs newEnd(尾尾)

      • oldStart vs newEnd(头尾)

      • oldEnd vs newStart(尾头)

    • 匹配成功则移动指针,否则通过key查找匹配节点。

  • key的作用(必考点):

    • 唯一标识节点,帮助diff算法高效复用节点。

    • key:采用“就地复用”策略,可能导致渲染错误(如列表顺序错乱)。

    • key:通过key匹配旧节点,实现移动、复用或删除,避免冗余操作。


4. 性能优化点

  • 时间复杂度:O(n),通过双端比较和key优化,避免O(n³)的暴力对比。

  • 惰性更新:非活跃组件不触发diff(如v-iffalse时)。

  • 静态提升:编译时标记静态节点,diff时直接跳过。


5. 面试金句总结

“Vue的diff算法基于同层比较双端优化,通过key高效复用节点,仅更新差异部分。核心是最小化DOM操作,避免全量渲染,提升性能。”


常见面试追问

  • Q:为什么不用indexkey
    A:index在列表增删时会变化,导致节点误匹配(如顺序错乱),应使用唯一ID。

  • Q:diff算法和React的异同?
    A:核心思想相似(同层比较),但Vue采用双端比较,React早期用递归(React 16后改用Fiber架构)。

  • Q:哪些场景会触发diff?
    A:响应式数据变化(如data更新)、props变化、强制更新(this.$forceUpdate())等。


评论