虚拟 DOM 与 Diff 算法
文章目录前言一、什么是虚拟 DOM1.1 定义1.2 为什么需要1.3 并非总是更快二、VNode 结构2.1 基本字段2.2 常见类型三、更新流程四、Vue 2 双端 Diff4.1 算法思路4.2 特点五、Vue 3 快速 Diff5.1 为什么放弃双端 Diff5.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 为什么改 Diff9.3 PatchFlag 做什么9.4 Block Tree 是什么十、易混淆点十一、思考与练习总结前言虚拟 DOM 是 Vue 渲染层的核心机制用 JavaScript 对象描述 DOM通过 Diff 算法找出最小变更并批量更新。本篇会讲清楚VNode 结构与更新流程Vue 2 双端 Diff vs Vue 3 快速 Diff最长递增子序列LIS与编译时优化概览一、什么是虚拟 DOM1.1 定义虚拟 DOM 是用 JavaScript 对象描述真实 DOM 结构的轻量级表示。状态变化时生成新的 VNode 树与旧树 Diff 后只把差异应用到真实 DOM。// 真实 DOMdivclassboxh1Hello/h1/div// 虚拟 DOMVNode 示意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 树 Diffpatch ↓ 计算出最小变更集增删改移 ↓ 批量应用到真实 DOM// 简化 Diff 思路functionpatch(oldVNode,newVNode){if(oldVNode.type!newVNode.type){// 类型不同 → 替换节点replaceNode(oldVNode,newVNode)return}// 同类型 → 比 props、比 childrenpatchProps(oldVNode,newVNode)patchChildren(oldVNode,newVNode)}四、Vue 2 双端 Diff4.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 快速 Diff5.1 为什么放弃双端 DiffVue 3 借鉴 Inferno 的快速 Diff目标减少不必要的节点比较次数用最长递增子序列LIS优化列表移动操作少做 DOM insert/move5.2 快速 Diff 流程列表1. 从头同步新旧节点 type key 相同则 patch不同则停 2. 从尾同步同上从尾部向前 3. 中间段用 key → index 映射处理新增、删除、移动 4. 移动优化对需要移动的节点求 LISLIS 内节点不移动其余按需 insert5.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)动态 classSTYLE (4)动态 stylePROPS (8)动态 props…组合标记Diff 时若 patchFlag 为 0可跳过该节点子树比较有标记则只比较标记部分。6.2 Block Tree扁平化动态节点将模板中的动态节点收集到dynamicChildren数组Diff 时只遍历动态节点静态子树整段跳过。div p静态标题/p !-- 静态不参与 Diff -- p{{ msg }}/p !-- 动态进入 dynamicChildren -- span{{ count }}/span !-- 动态进入 dynamicChildren -- /div6.3 静态提升纯静态节点提升到 render 函数外只创建一次后续 render 直接复用避免重复生成 VNode。编译优化的细节PatchFlag 类型、Block 收集规则等在编译优化专题中展开。七、key 与 Diff 的关系简述列表 Diff 依赖key判断「同一节点」相同 key 相同 type → patch复用 DOM不同 key → 销毁旧节点创建新节点key 不稳定如用 index 做增删会导致错误复用。key 的完整原理见专题「Key 的作用与原理」。八、与 React 的对比对比项Vue 3ReactDiff 粒度组件级 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静态子树整段跳过。十、易混淆点虚拟 DOM ≠ 更快是开发模型和批量更新策略不是性能银弹。Diff 只做同级比较不会跨层级移动节点O(n) 层级比较。Vue 2 / Vue 3 列表 Diff 不同Vue 3 用快速 Diff LIS。PatchFlag 是编译产物手写 render 函数默认无此优化。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 可能更省。总结虚拟 DOMJS 对象描述 DOM声明式 批量更新 跨平台更新流程新 VNode → Diff → 最小 patch → 真实 DOMVue 2双端 Diff依赖 keyVue 3快速 Diff LISPatchFlag、Block Tree、静态提升减少 Diff 量本质虚拟 DOM 是工程权衡不是「一定比原生 DOM 快」

相关新闻

范畴论中的胞腔构造:从拓扑直觉到同伦代数的统一框架

范畴论中的胞腔构造:从拓扑直觉到同伦代数的统一框架

1. 项目概述:从拓扑到范畴的思维跃迁如果你接触过代数拓扑,一定对“胞腔”这个概念不陌生。在经典的拓扑学里,我们把复杂的空间,比如一个球面、一个环面,甚至更诡异的形状,想象成是由一些基本的“砖块”——…

2026/6/26 23:59:02阅读更多 →
Java数组与链表终极对决:谁更胜一筹?

Java数组与链表终极对决:谁更胜一筹?

数组与链表对决:Java 中两种基础数据结构的全面对比在 Java 编程中,数组(Array)和链表(LinkedList)是最基础的数据结构,它们在存储和处理数据时有本质差异。以下分析从定义、结构、操作效率、内…

2026/6/26 23:59:02阅读更多 →
5个关键步骤掌握WE Learn智能助手:提升在线学习效率的完整指南

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

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

2026/6/26 23:54:01阅读更多 →
测试流量、测试粉丝

测试流量、测试粉丝

💎【行业认证权威头衔】 ✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家 ✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主 ✔ 技术生态共建先锋&am…

2026/6/27 1:19:12阅读更多 →
ID 生成方案

ID 生成方案

【MySQL】一篇讲透MySQL的MVCC机制!大数据毕业设计选题推荐-基于大数据的全球用水量数据可视化分析系统-大数据-Spark-Hadoop-Bigdata【全志V821_FoxPi】3-3 Linux 5.4 I2C FT6336U触摸 tslib LVGL从静态图表到交互叙事:数据可视化的新范式与实现第2集&a…

2026/6/27 1:19:12阅读更多 →
Day 30 - 错误、异常与 JSON 数据 - Python学习笔记

Day 30 - 错误、异常与 JSON 数据 - Python学习笔记

【Linux】线程同步和生产者消费者模型大模型面经(一) Prompt RAG 微调 新手MacBook Pro 使用指南Effective STL 第1条:慎重选择容器类型Vue keep-aliveEffective Python 第38条:简单的接口应该接受函数,而不是类的实例…

2026/6/27 1:19:12阅读更多 →
AI智能体赋能文化传承与创新领域:面向“大过滤器”危机的多文明星际探索叙事建构

AI智能体赋能文化传承与创新领域:面向“大过滤器”危机的多文明星际探索叙事建构

Raspberry Pi Pico GPIOchrome-devtools-mcp windows 环境安装解决 Azure DevOps Agent 的 SPNEGO 凭据错误问题【Rust GUI开发入门】编写一个本地音乐播放器(15. 记录运行日志)设计模式:单例模式。饿汉式、懒汉式Java SE “面向对象”面试清…

2026/6/27 1:19:12阅读更多 →
ubuntu20.04编译qt源码5.15.3

ubuntu20.04编译qt源码5.15.3

腾讯云COS通过CDN加速配置指南Linux内核进程管理子系统有什么第六十二回 —— 进程主结构详解(58)【漫士】傅里叶变换,不过就是坐标分解而言从《Life of A Pixel》来看Chrome的渲染机制(免费分享)基于python的飞机大战游戏【第五章:计算机视觉…

2026/6/27 1:19:12阅读更多 →
终极Fansly下载指南:简单3步批量保存所有内容

终极Fansly下载指南:简单3步批量保存所有内容

终极Fansly下载指南:简单3步批量保存所有内容 【免费下载链接】fansly-downloader Easy to use fansly.com content downloading tool. Written in python, but ships as a standalone Executable App for Windows too. Enjoy your Fansly content offline anytime,…

2026/6/27 1:14:12阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/26 11:03:22阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/26 4:15:25阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/26 9:29:01阅读更多 →
10分钟AI语音克隆与实时变声:Retrieval-based-Voice-Conversion-WebUI完整指南

10分钟AI语音克隆与实时变声:Retrieval-based-Voice-Conversion-WebUI完整指南

10分钟AI语音克隆与实时变声&#xff1a;Retrieval-based-Voice-Conversion-WebUI完整指南 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI Easily train a good VC model with voice data < 10 mins! 项目地址: https://gitcode.com/GitHub_Trending/re/Retrie…

2026/6/27 0:04:03阅读更多 →
Layerdivider:3分钟AI智能分层,彻底告别手动抠图时代

Layerdivider:3分钟AI智能分层,彻底告别手动抠图时代

Layerdivider&#xff1a;3分钟AI智能分层&#xff0c;彻底告别手动抠图时代 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 还在为复杂的图像分层工作烦…

2026/6/27 0:04:03阅读更多 →
Tomcat中X-Frame-Options配置实战:防御点击劫持的四种方法与最佳实践

Tomcat中X-Frame-Options配置实战:防御点击劫持的四种方法与最佳实践

1. 项目概述&#xff1a;为什么X-Frame-Options是Web安全的“防盗门”&#xff1f;最近在排查一个老项目的安全审计报告时&#xff0c;又被提到了“点击劫持”风险&#xff0c;矛头直指缺失的X-Frame-Options响应头。这已经不是第一次了&#xff0c;很多开发团队&#xff0c;尤…

2026/6/27 0:04:03阅读更多 →