CodeWalk

Vue 虚拟 DOM 和 diff 算法的原理是什么?

作者:苦行僧 · 2026-05-30 12:55

请说明 Vue 的虚拟 DOM 如何工作,以及其 diff 算法(双端比较)的核心流程。

回答

苦行僧

虚拟 DOM(Virtual DOM):用 JavaScript 对象描述真实 DOM 结构的树形数据结构。

// VNode 结构
{
  tag: 'div',
  props: { class: 'container' },
  children: [
    { tag: 'span', props: {}, children: 'Hello' }
  ]
}

为什么要用虚拟 DOM

  • 最小化真实 DOM 操作(昂贵)
  • 跨平台渲染(DOM/Canvas/SSR/原生)
  • 提供声明式编程能力

Vue diff 算法(双端比较)

  • 对两个同层 VNode 数组进行比较
  • 核心:头尾指针对比,尽量减少移动

流程(源码 patchChildren):

旧: [A, B, C, D]      新: [B, A, D, E]
         ↑oldStart              ↑newStart
         ↓oldEnd                ↓newEnd

Step 1: 比较 oldStart 和 newStart → A vs B ❌
Step 2: 比较 oldEnd 和 newEnd → D vs E ❌
Step 3: 比较 oldStart 和 newEnd → A vs E ❌
Step 4: 比较 oldEnd 和 newStart → D vs B ❌
Step 5: 用 key 查找新节点在旧节点中的位置
最终:B 移动到头部,D 删除,E 新增

优化策略

  • 同类型比较:标签名 + key 决定是否复用
  • 静态标记(PatchFlags):Vue 3 模板编译时标记动态绑定的位置(class/text/props),diff 时只检查标记过的节点
  • Block Tree:跳过静态结构,只 diff 动态节点

Vue 3 vs React diff

  • Vue 3:模板编译优化(PatchFlags + Block Tree),运行期只需对比动态节点
  • React:JSX 无编译优化,运行期完全 diff
  • Vue 3 性能通常优于 React(同等工作量下)