news 2026/5/2 21:21:23

Vue2 与 Vue3 虚拟DOM更新原理深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue2 与 Vue3 虚拟DOM更新原理深度解析

Vue2 与 Vue3 虚拟DOM更新原理深度解析

1. Vue2的虚拟DOM更新机制

1.1 响应式系统基础

Vue2的响应式系统基于Object.defineProperty实现。初始化时,Vue会递归遍历data对象的所有属性,将其转换为getter/setter。

// 简化的响应式原理functiondefineReactive(obj,key,val){Object.defineProperty(obj,key,{get(){// 依赖收集dep.depend()returnval},set(newVal){if(newVal===val)returnval=newVal// 触发更新dep.notify()}})}

每个组件实例对应一个Watcher,当数据变化时,会通知Watcher触发更新。

1.2 虚拟DOM结构与patch过程

Vue2使用snabbdom库的虚拟DOM实现。当数据变化时,会生成新的虚拟DOM树,然后与旧的虚拟DOM树进行对比(diff算法)。

虚拟DOM节点结构

constvnode={tag:'div',data:{attrs:{id:'app'},on:{click:handler}},children:[{tag:'span',text:'Hello'}]}

1.3 Diff算法核心逻辑(双端比较)

Vue2的diff算法采用双端比较策略,对比新旧子节点数组:

  1. 新旧头节点比较:如果相同,直接patch,指针后移
  2. 新旧尾节点比较:如果相同,直接patch,指针前移
  3. 旧头与新尾比较:如果相同,移动节点到末尾
  4. 旧尾与新头比较:如果相同,移动节点到开头
  5. key映射查找:通过key建立旧节点的索引图,查找可复用的节点
// 简化的diff核心逻辑functionupdateChildren(parentElm,oldCh,newCh){letoldStartIdx=0,newStartIdx=0letoldEndIdx=oldCh.length-1letnewEndIdx=newCh.length-1while(oldStartIdx<=oldEndIdx&&newStartIdx<=newEndIdx){// 四种比较情况if(sameVnode(oldCh[oldStartIdx],newCh[newStartIdx])){// 情况1:头头相同patchVnode(...)oldStartIdx++newStartIdx++}elseif(sameVnode(oldCh[oldEndIdx],newCh[newEndIdx])){// 情况2:尾尾相同patchVnode(...)oldEndIdx--newEndIdx--}// ... 其他情况}}

1.4 双端比较Diff算法流程图

1.5 更新流程

  1. 数据变化触发setter
  2. 通知依赖的Watcher
  3. Watcher调用updateComponent
  4. 执行render()生成新VNode
  5. 执行patch(oldVnode, newVnode)
  6. 应用diff算法更新真实DOM

2. Vue3的虚拟DOM更新机制

2.1 响应式系统重构

Vue3使用Proxy替代Object.defineProperty,实现了更完善的响应式系统:

  • 可以监听动态添加的属性
  • 可以监听数组索引和length变化
  • 性能更好,无需递归遍历
// Vue3响应式原理简例functionreactive(target){returnnewProxy(target,{get(target,key,receiver){track(target,key)// 依赖收集returnReflect.get(...arguments)},set(target,key,value,receiver){constresult=Reflect.set(...arguments)trigger(target,key)// 触发更新returnresult}})}

2.2 编译时优化

Vue3在编译阶段进行了多项优化:

2.2.1 静态提升(Static Hoisting)

静态节点在编译时被提升到render函数外部,避免重复创建:

// 编译前constApp={render(){returnh('div',[h('div',{class:'header'},'Header'),// 静态h('div',this.dynamicContent)// 动态])}}// 编译后consthoisted=h('div',{class:'header'},'Header')// 提升到外部constApp={render(){returnh('div',[hoisted,// 直接引用h('div',this.dynamicContent)])}}
2.2.2 Patch Flags(补丁标志)

为动态节点添加标志,只更新需要更新的部分:

// 编译时标记动态绑定constvnode={type:'div',children:[{type:'span',children:ctx.name,patchFlag:1}// TEXT 变化]}
2.2.3 Tree Flattening(树结构打平)

将动态子节点扁平化存储,减少diff时的递归深度:

// 编译优化<div><span>static</span><span>{{dynamic}}</span><span>static</span></div>// 编译后const_hoisted_1=/*静态节点1*/const_hoisted_2=/*静态节点2*/render(){returnh('div',[_hoisted_1,h('span',ctx.dynamic,1/* TEXT */),_hoisted_2])}// 动态子节点单独存储在dynamicChildren数组中

2.3 Diff算法优化

Vue3的diff算法进行了重大优化,采用预处理 + 最长递增子序列策略:

  1. 预处理:先处理相同的前缀和后缀节点
  2. 建立映射:为剩余旧节点建立key到索引的映射
  3. LIS算法:使用最长递增子序列算法最小化移动操作

2.4 Vue3的Diff算法流程图

2.5 LIS算法原理简析

最长递增子序列算法用于找到数组中保持原有顺序的最长子序列:

// 示例:找到最长递增子序列functionlis(arr){constp=arr.slice()constresult=[0]leti,j,u,v,cfor(i=0;i<arr.length;i++){constcurrent=arr[i]if(current!==0){j=result[result.length-1]if(arr[j]<current){p[i]=j result.push(i)continue}// 二分查找u=0v=result.length-1while(u<v){c=((u+v)/2)|0if(arr[result[c]]<current){u=c+1}else{v=c}}if(current<arr[result[u]]){if(u>0){p[i]=result[u-1]}result[u]=i}}}u=result.length v=result[u-1]while(u-->0){result[u]=v v=p[v]}returnresult}

2.6 Fragment和Portal支持

Vue3原生支持Fragment(多根节点)和Portal(传送门),减少不必要的包装元素。

3. Vue3相较于Vue2的提升与差异

3.1 性能提升对比

方面Vue2Vue3提升原因
初始渲染较慢快1.3-2倍静态提升、Tree Flattening
更新性能较慢快1.3-2倍Patch Flags、优化diff
内存占用较高减少约50%更细粒度的响应式跟踪
编译大小完整版~33KB~10KB更好的Tree Shaking

3.2 响应式系统差异

// Vue2的限制constobj={a:1}this.$set(obj,'b',2)// 需要特殊API添加响应式属性// Vue3无此限制constobj=reactive({a:1})obj.b=2// 直接添加,自动响应式

3.3 更新粒度优化

Vue2:组件级更新,即使只有少量数据变化也需重新渲染整个组件
Vue3:元素级更新,通过Patch Flags实现靶向更新

3.4 编译策略差异

Vue2:运行时编译为主,优化有限
Vue3:编译时优化为主,生成更高效的渲染函数

4. 未来发展趋势与Vue Vapor模式

4.1 Vue Vapor模式:无虚拟DOM的尝试

Vue Vapor是Vue团队探索的一种新模式,完全放弃虚拟DOM,直接操作DOM:

核心特点

  1. 响应式驱动的细粒度更新:每个响应式值直接绑定到DOM更新
  2. 编译器生成命令式代码:模板编译为直接操作DOM的指令
  3. 极致的性能:消除虚拟DOM diff开销
// 传统虚拟DOM方式functionrender(){returnh('div',{class:this.isActive?'active':''})// Vapor模式(概念性)functionsetup(){constisActive=ref(false)// 编译器生成constel=document.createElement('div')effect(()=>{el.className=isActive.value?'active':''})returnel}

4.2 发展趋势分析

4.2.1 编译时优化进一步加强
  • 更多静态分析
  • 更智能的代码生成
  • 类型导向的优化
4.2.2 混合架构的兴起
  • 虚拟DOM与命令式更新结合
  • 按需选择更新策略
  • 渐进式迁移方案
4.2.3 响应式系统的进一步精炼
  • 更细粒度的依赖跟踪
  • 自动依赖优化
  • 并发更新支持
4.2.4 开发体验的持续改进
  • 更好的TypeScript支持
  • 更智能的开发工具
  • 更简洁的API设计

4.3 对开发者的影响

  1. 性能敏感场景:Vapor模式可能成为首选
  2. 现有项目:虚拟DOM模式长期支持,无需立即迁移
  3. 学习曲线:需要理解不同模式的适用场景
  4. 生态系统:插件和工具需要适配多模式

4.4 结论与建议

短期(1-2年)

  • Vue3虚拟DOM模式仍是主流
  • Vapor模式在实验阶段
  • 建议新项目使用Vue3 + Composition API

中期(2-3年)

  • 混合模式逐渐成熟
  • 根据场景选择合适模式
  • 性能敏感应用可考虑Vapor

长期

  • 编译器更加智能
  • 多种模式并存
  • 开发者无需关心底层实现差异

5. 两种Diff算法对比总结

5.1 时间复杂度对比

操作类型Vue2 DiffVue3 Diff优化说明
最好情况O(n)O(1)Vue3的静态提升和快速路径
平均情况O(n)O(n)两者都是线性复杂度
最坏情况O(n²)O(n log n)Vue3的LIS算法更优
节点移动O(n)O(n) + LIS优化Vue3最小化移动操作

5.2 算法策略差异

  1. Vue2采用双端比较:从两端向中间比较,适合顺序变化的场景
  2. Vue3采用预处理+LIS:先处理边界,再使用LIS优化中间乱序部分

5.3 实际性能影响

在以下场景中,Vue3表现更优:

  • 大型列表的重新排序
  • 频繁的动态更新
  • 静态内容较多的页面
  • 组件嵌套较深的场景

Vue的演化体现了前端框架发展的典型路径:从声明式抽象到底层优化,再到性能极致的追求。虚拟DOM作为桥梁,在开发体验和性能之间取得了良好平衡。而Vapor模式的探索,则代表了框架对极致性能的追求。无论哪种模式,Vue团队始终在开发体验和运行性能之间寻找最佳平衡点,这是Vue能够持续成功的关键所在。

虚拟DOM的优化历程体现了从"通用算法"到"针对性优化"的演进,未来随着Vapor模式的发展,我们可能会看到更多混合策略的出现,在不同的场景下选择最优的更新策略。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/2 11:59:32

EMD分解与希尔伯特变换能量谱分析

如何对信号进行经验模态分解(EMD)&#xff0c;然后对各个本征模态函数(IMF)进行希尔伯特变换&#xff0c;最终获得能量谱的完整MATLAB实现。 算法原理概述 EMD Hilbert变换流程 原始信号 → EMD分解 → 多个IMF分量 残差→ 对每个IMF进行Hilbert变换 → 解析信号→ 计算瞬时频…

作者头像 李华
网站建设 2026/5/1 8:36:39

网站建设公司找哪家

网站建设公司找哪家&#xff1f;行业深度解析引言在当今数字化时代&#xff0c;网站已成为企业展示形象、拓展业务的重要窗口。因此&#xff0c;选择一家合适的网站建设公司至关重要。那么&#xff0c;企业在寻找网站建设公司时应考虑哪些因素呢&#xff1f;一、专业实力是基础…

作者头像 李华
网站建设 2026/4/25 3:54:53

Python语法基础笔记(三)

一、列表 list定义&#xff1a;是处理一组有序项目的数据结构格式&#xff1a;列表名 [ 元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;元素4&#xff0c;……]注意&#xff1a;列表的所有元素放在一对中括号" [] "中&#xff0c;并使用逗号 “&#xff0c;”…

作者头像 李华
网站建设 2026/5/1 8:47:26

Windows系统文件scrptadm.dll丢失损坏 无法运行软件 下载修复

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/5/1 8:54:45

开源鸿蒙跨平台开发训练营--AtomGit(GitCode)口袋工具(七)

我们继续接着上一章的内容&#xff0c;完成文件内容的显示。显示文件内容1. 调整侧边栏内容上一章&#xff0c;我们侧边栏只显示了根目录下的文件和文件夹。这一张我们要将其显示成一个可折叠和展开的文件树。目的是为了可以让用户在侧边栏中切换想要查看的文件。GitCodeCodeRe…

作者头像 李华
网站建设 2026/5/1 10:04:35

【鸿蒙开发案例篇】基于MindSpore Lite的端侧人物图像分割案例

大家好&#xff0c;我是 V 哥。今天的内容咱们来详细介绍鸿蒙开发中&#xff0c;如何使用MindSpore Lite在鸿蒙系统上实现端侧人物图像分割功能&#xff0c;以及提供完整的实现方案。 联系V哥获取 鸿蒙学习资料 系统架构设计 技术栈与组件关系 #mermaid-svg-kKMHq6sLNO6nbkY…

作者头像 李华