news 2026/6/26 23:58:28

虚拟 DOM 与 Diff 算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
虚拟 DOM 与 Diff 算法

文章目录

  • 前言
  • 一、什么是虚拟 DOM
    • 1.1 定义
    • 1.2 为什么需要
    • 1.3 并非总是更快
  • 二、VNode 结构
    • 2.1 基本字段
    • 2.2 常见类型
  • 三、更新流程
  • 四、Vue 2 双端 Diff
    • 4.1 算法思路
    • 4.2 特点
  • 五、Vue 3 快速 Diff
    • 5.1 为什么放弃双端 Diff
    • 5.2 快速 Diff 流程(列表)
    • 5.3 最长递增子序列(LIS)
  • 六、Vue 3 编译时优化(概览)
    • 6.1 PatchFlag:标记动态节点
    • 6.2 Block Tree:扁平化动态节点
    • 6.3 静态提升
  • 七、key 与 Diff 的关系(简述)
  • 八、与 React 的对比
  • 九、面试聚焦
    • 9.1 虚拟 DOM 并非总是更快
    • 9.2 Vue 3 为什么改 Diff?
    • 9.3 PatchFlag 做什么?
    • 9.4 Block Tree 是什么?
  • 十、易混淆点
  • 十一、思考与练习
  • 总结

前言

虚拟 DOM 是 Vue 渲染层的核心机制:用 JavaScript 对象描述 DOM,通过 Diff 算法找出最小变更并批量更新。本篇会讲清楚:

  • VNode 结构与更新流程
  • Vue 2 双端 Diff vs Vue 3 快速 Diff
  • 最长递增子序列(LIS)与编译时优化概览

一、什么是虚拟 DOM

1.1 定义

虚拟 DOM 是用 JavaScript 对象描述真实 DOM 结构的轻量级表示。状态变化时生成新的 VNode 树,与旧树 Diff 后,只把差异应用到真实 DOM。

// 真实 DOM<divclass="box"><h1>Hello</h1></div>// 虚拟 DOM(VNode 示意)constvnode={type:'div',props:{class:'box'},children:[{type:'h1',children:'Hello'}]}

1.2 为什么需要

问题虚拟 DOM 的解决
直接操作 DOM 慢且难追踪声明式描述 UI,框架算最优更新
多次状态变更多次 DOM 操作合并为一次批量更新
跨平台(Web / SSR / 小程序)同一套 VNode 可对接不同渲染器

1.3 并非总是更快

极少量的 DOM 更新时,手动改 DOM 可能更快。虚拟 DOM 的价值在于复杂场景下的声明式开发、批量更新和跨平台抽象,而不是「一定比原生 DOM 快」。


二、VNode 结构

2.1 基本字段

constvnode={type:'div',// 标签名、组件、Fragment 等props:{class:'box'},children:[],key:'unique-id',// 列表 Diff 用el:null,// 运行时关联的真实 DOMpatchFlag:0,// Vue 3 编译时标记(见下文)dynamicChildren:null// Vue 3 Block Tree 动态子节点}

2.2 常见类型

// 文本{type:Text,children:'hello'}// 元素{type:'div',props:{},children:[]}// 组件{type:MyComponent,props:{msg:'hi'}}// Fragment(多根节点){type:Fragment,children:[...]}

三、更新流程

响应式数据变化 ↓ 触发组件 re-render,生成新 VNode 树 ↓ 新旧 VNode 树 Diff(patch) ↓ 计算出最小变更集(增删改移) ↓ 批量应用到真实 DOM
// 简化 Diff 思路functionpatch(oldVNode,newVNode){if(oldVNode.type!==newVNode.type){// 类型不同 → 替换节点replaceNode(oldVNode,newVNode)return}// 同类型 → 比 props、比 childrenpatchProps(oldVNode,newVNode)patchChildren(oldVNode,newVNode)}

四、Vue 2 双端 Diff

4.1 算法思路

Vue 2 对同级列表使用双端比较:新旧数组各设头尾指针,从两端向中间同时比较,尽量复用 DOM。

旧: A B C D ↑ ↑ oldStart oldEnd 新: D A B C ↑ ↑ newStart newEnd 比较顺序(共 4 种): 1. oldStart vs newStart 2. oldEnd vs newEnd 3. oldStart vs newEnd 4. oldEnd vs newStart 都不匹配 → 用 key 在旧列表中查找

4.2 特点

  • 适合列表头尾增删、反转等常见场景
  • 依赖key做节点身份识别
  • 最坏情况仍需较多比较,Vue 3 做了进一步优化

五、Vue 3 快速 Diff

5.1 为什么放弃双端 Diff

Vue 3 借鉴 Inferno 的快速 Diff,目标:

  • 减少不必要的节点比较次数
  • 最长递增子序列(LIS)优化列表移动操作,少做 DOM insert/move

5.2 快速 Diff 流程(列表)

1. 从头同步:新旧节点 type + key 相同则 patch,不同则停 2. 从尾同步:同上,从尾部向前 3. 中间段:用 key → index 映射处理新增、删除、移动 4. 移动优化:对需要移动的节点求 LIS,LIS 内节点不移动,其余按需 insert

5.3 最长递增子序列(LIS)

旧: [A, B, C, D, E] 新: [A, C, D, B, E] (B 从 index 1 移到 index 3) 需要移动的: B LIS 帮助找出「已经相对有序、不必动」的节点,减少 DOM 移动次数

LIS 让 Diff 在「乱序但可复用」的列表里,用最少 DOM 移动完成更新。


六、Vue 3 编译时优化(概览)

Diff 之外,Vue 3 在编译阶段减少需要 Diff 的节点量:

6.1 PatchFlag:标记动态节点

编译器分析模板,给 VNode 打上「哪里会变」的标记:

// 编译结果示意createElementVNode('div',{class:'static'},createTextVNode('hello',PatchFlags.TEXT)// 仅文本会变)
PatchFlag含义
TEXT (1)动态文本
CLASS (2)动态 class
STYLE (4)动态 style
PROPS (8)动态 props
组合标记

Diff 时若 patchFlag 为 0,可跳过该节点子树比较;有标记则只比较标记部分。

6.2 Block Tree:扁平化动态节点

将模板中的动态节点收集到dynamicChildren数组,Diff 时只遍历动态节点,静态子树整段跳过。

<div> <p>静态标题</p> <!-- 静态,不参与 Diff --> <p>{{ msg }}</p> <!-- 动态,进入 dynamicChildren --> <span>{{ count }}</span> <!-- 动态,进入 dynamicChildren --> </div>

6.3 静态提升

纯静态节点提升到 render 函数外,只创建一次,后续 render 直接复用,避免重复生成 VNode。

编译优化的细节(PatchFlag 类型、Block 收集规则等)在编译优化专题中展开。


七、key 与 Diff 的关系(简述)

列表 Diff 依赖key判断「同一节点」:

  • 相同 key + 相同 type → patch(复用 DOM)
  • 不同 key → 销毁旧节点,创建新节点

key 不稳定(如用 index 做增删)会导致错误复用。key 的完整原理见专题「Key 的作用与原理」。


八、与 React 的对比

对比项Vue 3React
Diff 粒度组件级 + Block 内动态节点Fiber 可中断的增量 Diff
列表算法快速 Diff + LIS单端 + key 映射
编译优化PatchFlag、静态提升、Block Tree部分优化,策略不同

两者都用虚拟 DOM,但 Diff 策略和编译优化路径不同。


九、面试聚焦

9.1 虚拟 DOM 并非总是更快

简单场景手动 DOM 可能更快;虚拟 DOM 的价值是声明式、批量更新、跨平台。

9.2 Vue 3 为什么改 Diff?

双端 Diff 在复杂列表下比较次数仍偏多;快速 Diff + LIS 减少移动,配合 PatchFlag / Block Tree 减少比较范围。

9.3 PatchFlag 做什么?

编译期标记 VNode 哪些部分动态,Diff 时跳过静态内容,只更新标记位。

9.4 Block Tree 是什么?

把动态节点扁平收集,Diff 只比 dynamicChildren,静态子树整段跳过。


十、易混淆点

  1. 虚拟 DOM ≠ 更快:是开发模型和批量更新策略,不是性能银弹。
  2. Diff 只做同级比较:不会跨层级移动节点(O(n) 层级比较)。
  3. Vue 2 / Vue 3 列表 Diff 不同:Vue 3 用快速 Diff + LIS。
  4. PatchFlag 是编译产物:手写 render 函数默认无此优化。
  5. Shadow DOM ≠ Virtual DOM:前者是 Web Components 浏览器封装,与框架 VNode 无关。

十一、思考与练习

1.虚拟 DOM 的更新流程是什么?

解析:数据变 → 新 VNode → 与旧 VNode Diff → 最小变更 → 更新真实 DOM。

2.Vue 2 和 Vue 3 列表 Diff 有何不同?

解析:Vue 2 双端比较;Vue 3 快速 Diff,头尾同步 + 中间 key 映射 + LIS 优化移动。

3.LIS 在 Diff 中的作用?

解析:找出相对有序、不必移动的节点,减少 DOM insert/move 次数。

4.PatchFlag 和 Block Tree 解决什么问题?

解析:减少 Diff 范围——只比动态节点、只更新标记为动态的部分,静态内容跳过。

5.为什么说虚拟 DOM 不总是更快?

解析:创建 VNode 和 Diff 本身有开销;极简单更新直接改 DOM 可能更省。


总结

  • 虚拟 DOM:JS 对象描述 DOM,声明式 + 批量更新 + 跨平台
  • 更新流程:新 VNode → Diff → 最小 patch → 真实 DOM
  • Vue 2:双端 Diff,依赖 key
  • Vue 3:快速 Diff + LIS;PatchFlag、Block Tree、静态提升减少 Diff 量
  • 本质:虚拟 DOM 是工程权衡,不是「一定比原生 DOM 快」
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 23:57:13

GitHub 推出 Copilot 桌面应用,支持并行 Agent 开发工作流

GitHub 发布了 GitHub Copilot App。这是一款面向 Agent 原生开发的桌面应用&#xff0c;意在让开发者继续掌握主导权&#xff0c;同时将更多编码工作交给 AI Agent 完成。GitHub 产品副总裁 Mario Rodriguez 在官方博客中表示&#xff0c;最近一波编码 Agent 的兴起虽然提升了…

作者头像 李华
网站建设 2026/6/26 23:54:13

WELearn智能助手:3个核心场景帮你轻松提升学习效率90%

WELearn智能助手&#xff1a;3个核心场景帮你轻松提升学习效率90% 【免费下载链接】WELearnHelper 显示WE Learn随行课堂题目答案&#xff1b;支持班级测试&#xff1b;自动答题&#xff1b;刷时长&#xff1b;基于生成式AI(ChatGPT)的答案生成 项目地址: https://gitcode.co…

作者头像 李华
网站建设 2026/6/26 23:53:35

5个关键步骤掌握WE Learn智能助手:提升在线学习效率的完整指南

5个关键步骤掌握WE Learn智能助手&#xff1a;提升在线学习效率的完整指南 【免费下载链接】WELearnHelper 显示WE Learn随行课堂题目答案&#xff1b;支持班级测试&#xff1b;自动答题&#xff1b;刷时长&#xff1b;基于生成式AI(ChatGPT)的答案生成 项目地址: https://gi…

作者头像 李华
网站建设 2026/6/26 23:52:45

迈向医学人工智能科学家:全自动临床科研框架的逻辑解析

迈向医学人工智能科学家&#xff1a;全自动临床科研框架的逻辑解析 当香港中文大学、斯坦福大学和微软研究院的研究团队在2026年3月宣布推出“Medical AI Scientist”时&#xff0c;一个核心问题被推到台前&#xff1a;AI能否从“辅助工具”进化为“自主科研伙伴”&#xff1f;…

作者头像 李华
网站建设 2026/6/26 23:52:20

音频格式解密:ncmdump技术解析与跨平台音乐自由实践

音频格式解密&#xff1a;ncmdump技术解析与跨平台音乐自由实践 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 在数字音乐消费日益普及的今天&#xff0c;用户面临着平台格式壁垒带来的诸多困扰。网易云音乐的NCM加密格式虽然保护了…

作者头像 李华