当前位置: 首页 > java >正文

Vue 虚拟DOM和DIff算法

一. 什么是虚拟DOM?

虚拟DOM(Virtual DOM), 本质上是用js对象来描述DOM结构的树形数据,然后再通过特定的render方法将其渲染成真是的DOM 

它的主要作用是: 

  • 减少直接操作真实DOM带来的性能开销
  • 通过比较新旧虚拟DOM差异,只对变化的部分进行最小化更新

通俗理解: 

虚拟DOM就是"用对象模拟HTML结构",每次状态变更先修改对象,最后再批量同步到页面上 

二.为什么需要虚拟DOM ?

  1. 减少DOM操作频率; 浏览器DOM操作是昂贵的(重排,重绘),虚拟DOM允许我们"批量修改", 
  2. 跨平台: 虚拟DOM并不依赖浏览器DOM,本质是纯对象,可用于SSR,原生渲染等 
  3. 提高渲染性能: 通过diff算法,可以最小化更新真实DOM,提升性能  

三.虚拟DOM与真实DOM的区别 

项目虚拟 DOM(VNode)真实 DOM(DOM Element)
本质JS 对象(树)浏览器提供的 HTML 节点(树)
创建开销非常小,内存中构建较大,操作会触发浏览器重排和重绘
渲染位置内存中显示在网页上
修改方式对象属性直接修改需要调用原生 DOM API
依赖平台与平台无关(跨平台)依赖浏览器 DOM API
 1.虚拟dom 
const vnode = {tag: 'div',data: { id: 'app' },children: [{ tag: 'p', data: {}, children: [], text: 'Hello' },{ tag: 'button', data: {}, children: [], text: 'Click me' }],text: undefined,elm: undefined
}
  •  tag: 标签名
  • data: 表示该标签的属性(如id)
  • children 表示子元素 
  • text 表示文本内容
  • elm 用于存储实际的DOM元素引用 
2.真实的dom 
<div id="app"><p>Hello</p><button>Click me</button>
</div>

四.Diff 算法 : 虚拟DOM更新的核心 

1.为什么需要Diff算法?

每当数据发生变化时,Vue会重新渲染组件并生成一个新的虚拟DOM树,然后,Vue会比较新旧虚拟DOM树之间的差异,计算出最小化的DOM更新(这个过程叫做DIff),这样做的目的是以避免频繁地操真实DOM,减少重排和重绘,提升性能

DIff的核心思想 

Vue的DIff算法通过一下几个核心思想来高效比较新旧Vnode树:  

  • 同层比较: Vue会在同一层级上进行比较,而不会跨层比较,这意味着Vue会首先比较根节点,接着比较每个子节点, 
  • 双端比较: Vue的Diff算法通过从两端开始对比(即从头和尾同时对比)来最大化复用节点,这样可以减少不必要的比较 
  • 复用节点: 只有当新旧节点是同类型(sameVnode)是,Vue才会尝试复用旧的DOM元素,否则就会销毁旧节点并创建新节点 
  • 最小化更新: 通过计算出差异后,Vue只更新那些发生变化的部分,而不是重新渲染整个DOM树 
同层比较与双端比较  

Vue的Diff算法先比较两个虚拟DOM树的根节点,然后从根节点触发,依次比较左右子节点,采用"双端对比"的策略,即: 

1. 从头开始比较: 比较oldStart和newStart; 

2. 从尾开始比较: 比较oldEnd和newEnd; 

3. 尝试优化节点的复用,最小化DOM操作. 

具体流程
  1. 更新触发: 当响应式数据发生变化时,Vue会触发相应的Watcher 
  2. 重新渲染: Watcher会触发render( ),生成新的虚拟DOM(VNode)
  3. Diff比较: Vue将新的VNode和旧的Vnode进行比对,使用DIff算法计算最小的变化; 
  4. Patch更新: 计算出差异后,Vue会通过patch操作将差异应用到真实DOM上 

2.同一个虚拟节点(sameVnde)判断

function sameVnode(a,b){return a.key===b.key && a.tag===b.tag 
}
  • key: 当Vnode的key一样是,表示它们是同一类型的节点,Vue可以复用这个节点 
  • tag: tag相同表示它们是相同类型的元素(如div,p,button等)  

 3.Vnode和真实DOM更新过程Patch函数

Vue在执行更新时,会通过patch函数来进行DOm的更新,patch函数的核心就是对比新旧虚拟DOM节点的差异,然后通过最小化更新来优化DOM操作

function patch(oldVnode, vnode) {if (!sameVnode(oldVnode, vnode)) {const parent = oldVnode.elm.parentNode;const newElm = createElm(vnode);parent.insertBefore(newElm, oldVnode.elm);parent.removeChild(oldVnode.elm);} else {patchVnode(oldVnode, vnode);}
}
  • sameVnode: 首先判断是否是同一个节点
  • patchVnode: 如果是同一个节点,则执行节点的属性,文本,子节点等的更新
  • createElm: 如果节点类型不同,Vue会销毁旧节点并创建新节点 
patchVnode处理节点更新 
1. 更新文本: 如果新旧节点都是文本节点,只需要更新文本内容
2.更新子节点: 如果有子节点,Vue会调用updateChildren来执行子节点的更新
3.更新属性: 如果节点的属性(如class,style等)有变化,Vue会通过原生DOMAPI更新这些属性 

五. 总结 

Vue通过虚拟DOM和Diff算法,极大地优化了性能,当数据发生变化时,Vue会生成新的虚拟DOM,通过DIff算法与旧的虚拟DOM树对比,最终只更新有变化的部分,从而减少了直接操作真实DOM的次数,提升了页面的响应速度,结合合理的性能优化策略,可以让Vue在大规模应用中也能保持高效的性能 

http://www.xdnf.cn/news/3894.html

相关文章:

  • 从上帝视角看文件操作
  • 杜教筛原理,实现与时间复杂度分析
  • 【服务器通信-listen】——int listen(int sockfd, int backlog)
  • 【多次弹出“获取打开此tobiieyetracking链接的应用”的窗口】解决办法
  • [硬件电路-11]:模拟电路常见元器件 - 什么是阻抗、什么是输入阻抗、什么是输出阻抗?阻抗、输入阻抗与输出阻抗的全面解析
  • Python_leve2.1
  • Python语句入门:从基础到实践
  • STM32的定时器
  • 在Linux中如何创建自定义的systemd服务的步骤
  • 动静态库【Linux操作系统】
  • 股指期货风险管理功能及基差、升水、贴水的影响
  • 牛客月赛115 C题-命运之弹 题解
  • Linux环境下的进程创建、退出和进程等待
  • 谷歌 NotebookLM 支持生成中文播客
  • n8n 条件节点详解:IF 与 Switch 的多分支工作流设计
  • 虚函数VS虚拟继承:C++多重继承二义性破解与性能调优
  • 论快乐的学习和学习的快乐
  • 万字详解ADC药物Payload
  • Debezium 架构详解与实战示例
  • 【操作系统】深入理解内存管理:从虚拟内存到OOM Killer
  • cloudfare+gmail 配置 smtp 邮箱
  • 【CISCO】Se2/0, Se3/0:串行口(Serial) 这里串口的2/0 和 3/0分别都是什么?
  • React hooks详解
  • 快速外网访问,证书自动续约 | 极空间IPv4IPv6 DDNS 配置详解
  • 数据结构与算法:回溯
  • Python:Seaborn 美化图表的技术指南
  • 【五一培训】Day 4
  • 常用命令集合
  • PCB叠层设计方案
  • 探秘DeepSeek模型参数:解锁AI潜能的密码