Lazy loaded image
技术分享
Vue 的双端 Diff 算法
字数 863阅读时长 3 分钟
2023-7-9
2025-5-10
type
status
date
slug
summary
tags
category
icon
password

Vue 的双端 Diff 算法

Vue 中的虚拟 DOM diff 算法采用了“双端 Diff”策略,这是相较 React 的全量对比算法(如 React 16 以前版本中的递归对比)的一种性能优化手段。双端 Diff 在处理子节点列表变更时,能够以更高效的方式减少节点的移动操作。

一、为什么需要双端 Diff?

在虚拟 DOM 更新中,一个核心任务是比较新旧两个 vnode 列表,找出最小代价的节点变更。
传统的 diff 算法是“从头比到尾”,但如果一个列表中仅仅是头尾位置发生了变化,就会导致中间大量节点无意义的比较和移动。
双端 diff 则是从新旧两端同时进行比较,有效规避了这个问题。

二、算法流程解析

设:
  • oldStartIdx, oldEndIdx 指向旧 children 的头尾
  • newStartIdx, newEndIdx 指向新 children 的头尾
四种比较策略如下:
  1. oldStartVNode vs newStartVNode → 头对头
  1. oldEndVNode vs newEndVNode → 尾对尾
  1. oldStartVNode vs newEndVNode → 头对尾(可能是右移)
  1. oldEndVNode vs newStartVNode → 尾对头(可能是左移)

算法主循环

最后处理剩余部分

  • 若 old 中有剩余:卸载节点
  • 若 new 中有剩余:创建新节点

三、图示说明

为了帮助更清楚理解双端 Diff,我们用一张示意图说明对比过程:
notion image
图中展示了节点匹配的过程,从两端向中间移动,不断更新节点位置或复用。

四、双端 Diff 优势与局限

优势

  • 性能优秀:对于节点变化集中在头尾的场景(如表格分页、数据滚动),效果极佳。
  • 复用合理:通过 key 匹配和头尾策略,避免不必要的 DOM 操作。

局限

  • 复杂度偏高:实现起来较为复杂,不如简单的线性比较直观。
  • 不支持最小操作序列:双端 Diff 并非最优编辑距离算法(如 React Fiber 中使用的 LCS 最长公共子序列算法),某些场景下性能表现不如后者。

五、Vue 3 中的变化

Vue 3 在 Virtual DOM diff 中引入了基于 最长递增子序列(LIS)的优化策略,类似于 React 16+ 的策略,适用于大型列表的最优 diff。这一改变意味着 Vue 3 的 diff 更加精细化,也弥补了 Vue 2 双端 diff 的部分短板。

六、总结

Vue 的双端 diff 算法是一种在性能与复杂度之间平衡的策略,尤其适用于结构稳定、变化集中在两端的 DOM 更新场景。在 Vue 3 中,官方进一步引入更高效的 diff 优化手段,使得框架在处理复杂动态节点时更为可靠。
 
上一篇
23 年 8 月软件推荐
下一篇
React 18 与 Vue 3 对比