对比:Vue2 vs Vue3 Diff 算法

Vue3 在 Diff 算法上做了重大优化,通过 Block、静态提升、PatchFlag 等技术大幅提升了更新性能。


核心区别

维度Vue2Vue3
数据结构完整 VNode 树Block + 动态节点数组
Diff 范围遍历整棵 VNode 树只 diff 动态节点
静态节点每次参与 diff静态提升,不参与 diff
时间复杂度O(n)O(d),d=动态节点数

详细对比

1. 虚拟 DOM 结构

Vue2:树形结构

// 每次更新都需要遍历整棵树
vnode = {
  type: 'div',
  children: [
    { type: 'span', children: '静态' },   // 每次都 diff
    { type: 'span', children: this.msg }   // 动态
  ]
}

Vue3:Block + 动态集合

// 静态节点已提升,动态节点单独管理
block = {
  type: 'div',
  children: [...],
  dynamicChildren: [  // 只 diff 这部分
    dynamicNode1,
    dynamicNode2
  ]
}

2. Diff 性能

Vue2:遍历整棵树

function update(oldVNode, newVNode) {
  // 无论是否需要更新,都遍历所有节点
  traverseAndPatch(oldVNode.children, newVNode.children)
}

Vue3:只 diff 动态节点

function blockPatch(block, newBlock) {
  // 只 diff 动态节点集合
  block.dynamicChildren.forEach((child, i) => {
    patch(child, newBlock.dynamicChildren[i])
  })
}

3. 静态提升

Vue2:无静态提升

render() {
  return h('div', [
    h('span', '静态内容'),  // 每次都创建新 VNode
    h('span', this.msg)
  ])
}

Vue3:静态提升

// 静态内容提取到 render 函数外
const _hoisted_1 = h('span', '静态内容')
 
render() {
  return h('div', [
    _hoisted_1,  // 复用
    h('span', this.msg)
  ])
}

性能提升原因

flowchart TB
    subgraph Vue2 ["Vue2"]
        A[模板] --> B[完整 VNode 树]
        B --> C[Diff 整棵树]
    end

    subgraph Vue3 ["Vue3"]
        D[模板] --> E[静态提升]
        E --> F[动态节点标记]
        F --> G[Block 结构]
        G --> H[只 Diff 动态节点]
    end

    C --> I[On]
    H --> J[Od]

实际场景性能对比

场景Vue2Vue3提升
纯静态页面更新极快静态节点不参与
大列表更新中等只 diff 变化的行
频繁状态变化较慢精准 diff
首次渲染中等Block 有开销

为什么 Vue3 更快

  1. 减少 diff 范围:只 diff 动态节点
  2. 静态提升:不变的部分不参与 diff
  3. PatchFlag:标记动态内容位置,快速定位
  4. 更激进的优化:Vue2 时代无法实现的优化

知识图谱


参考延伸

  • Vue3 源码:packages/runtime-core/src/renderer.ts
  • Vue RFC: Block-based VNode