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

Vue——Diff算法

目录

什么是Diff算法?

比较方式

1. 同层比较

2. 双端比较

双端比较的步骤:

3. 通过 key 来优化比较

原理分析

1. 虚拟 DOM 和真实 DOM

2. Diff 算法的基本原理

3. 双端比较优化

4. 通过 key 进行优化

5. 具体操作

6. 原理总结


声明,此博客中部分图示来自网络

什么是Diff算法?

        Vue 的 diff 算法是一种高效的比较新旧虚拟 DOM 树(Virtual DOM)并更新真实 DOM 的机制。它通过尽量减少对 DOM 的操作来提高性能。以下是 diff 算法的关键概念:

  1. 虚拟 DOM:Vue 使用虚拟 DOM 来表示 UI。虚拟 DOM 是一个轻量级的 JavaScript 对象树,表示真实 DOM 的结构和内容。当数据发生变化时,Vue 通过虚拟 DOM 比较新旧状态,找到变化的地方。

  2. 同层比较:Vue 的 diff 算法只会比较同一层级的节点,不会跨层比较。这意味着当父节点不同,Vue 不会去比较它们的子节点,而是直接销毁旧的节点并创建新的节点。

  3. 双端比较:Vue 采用了一种优化策略,即从新旧虚拟 DOM 的两端同时进行比较,这称为 "双端比较"。它从头部和尾部同时进行比较,直到发现不匹配的节点,从而减少遍历的次数。

  4. 复用节点:当 Vue 发现新旧虚拟 DOM 中的节点相同(通过 key 属性判断),它会复用已有的 DOM 节点,而不是销毁旧的节点重新创建。这进一步提高了性能。

  5. 更新策略:Vue 会根据 diff 结果,生成最小化的 DOM 更新操作,更新真实 DOM。这种基于 diff 的更新策略可以减少不必要的 DOM 操作,从而提升页面的渲染效率。

       Vue 的 diff 算法核心在于高效比较新旧虚拟 DOM 树的差异,并通过最小化 DOM 操作来更新 UI,提高渲染性能。


比较方式

1. 同层比较

        Vue 的 diff 算法只会在同一层级的节点中进行比较,而不会跨层进行比较。这样可以减少复杂度,因为不用递归遍历所有节点。它假设 DOM 结构的变化不会引发大的层级变动,主要会集中在同层次的节点变化上。

2. 双端比较

        双端比较是一种优化策略,即 Vue 会同时从两边进行比较:既从头部(左端)开始,也从尾部(右端)开始。通过这种方式,它能更快地找到不匹配的节点。

双端比较的步骤:
  • 头部对比:先从新旧虚拟 DOM 的头部开始比较节点,如果相同,则更新节点并继续比较下一个。
  • 尾部对比:如果头部节点不同,Vue 会同时检查新旧虚拟 DOM 的尾部,看看尾部的节点是否相同。如果相同,则继续向中间移动比较。
  • 头尾交叉对比:如果头尾都不匹配,Vue 会进一步尝试新 DOM 的头部与旧 DOM 的尾部,或者新 DOM 的尾部与旧 DOM 的头部进行交叉比较。
  • 中间节点处理:如果头尾对比都没有找到匹配的节点,那么 Vue 会进入中间部分的处理,通过节点的 key 属性来精确定位和比较节点。

3. 通过 key 来优化比较

        在 diff 算法中,Vue 强烈建议为列表渲染的节点设置 key 属性,key 可以帮助 Vue 更精确地比较节点。没有 key 时,Vue 只能通过节点的顺序来匹配节点,但如果使用了 key,它会根据 key 值来复用、移动或删除节点,从而提高性能和渲染的正确性。

  • 相同的 key:如果新旧节点的 key 相同,Vue 会复用这个节点,并更新其内容。
  • 不同的 key:如果新旧节点的 key 不同,则 Vue 会删除旧节点并创建新的节点。

原理分析

        Vue 的 diff 算法的原理是基于虚拟 DOM的差异检测机制。通过比较新旧两棵虚拟 DOM 树,找到变化的地方,并仅对这些差异进行最小化的 DOM 操作,从而提高渲染效率。下面是 Vue diff 算法的工作原理:

1. 虚拟 DOM 和真实 DOM

  • 虚拟 DOM:Vue 会先将页面的结构和内容生成一个虚拟 DOM(用 JavaScript 对象表示的树),当数据发生变化时,Vue 会根据新的数据生成新的虚拟 DOM。
  • 比较新旧虚拟 DOM:每次组件的状态发生变化时,Vue 会对比新旧两棵虚拟 DOM 树,找出发生变化的部分,这个过程就是 diff。

2. Diff 算法的基本原理

Vue 的 diff 算法遵循以下原则:

  • 同层比较:只比较同一层级的节点,不会跨层次进行比较,这可以大大减少复杂度。因为层级的改变通常不常见,Vue 假定层级结构在大多数情况下保持不变。

  • 最小化操作:diff 算法的目的是找到新旧 DOM 树的最小差异,进而生成最少的 DOM 操作。操作越少,性能越高,因为 DOM 操作相对比较昂贵。

  • 递归深度优先:diff 算法采用深度优先搜索的方式,从根节点开始,递归比较每个子节点,直到找到最小的差异。

3. 双端比较优化

Vue 的 diff 算法进行了一些优化,例如双端比较策略,它加快了节点查找速度:

  1. 头部比较:首先从新旧虚拟 DOM 的头部开始,逐一对比节点,如果相同就继续比较下一个节点。
  2. 尾部比较:如果头部没有匹配,就从尾部开始比较新旧 DOM。
  3. 头尾交叉比较:如果头尾都没有匹配,则 Vue 会检查新虚拟 DOM 的头部与旧虚拟 DOM 的尾部,或者新虚拟 DOM 的尾部与旧虚拟 DOM 的头部,寻找匹配的节点。

向中间靠拢 

通过从两边同时进行比较,Vue 可以更快速地找到不匹配的节点,并减少遍历的次数。

4. 通过 key 进行优化

  • key 的作用:在渲染列表(例如 v-for 渲染的列表)时,Vue 会建议开发者为每个列表项提供唯一的 key,这是为了帮助 Vue 更准确地跟踪每个节点的变化。没有 key 时,Vue 只能根据节点的位置去匹配,这可能导致不必要的节点更新。

  • key 的匹配规则:如果 key 相同,Vue 会认为这是同一个节点,并复用该节点。若 key 不同,则认为这是一个新节点,旧节点会被销毁,新节点会被创建。

5. 具体操作

        当 Vue 比较出新旧虚拟 DOM 的差异后,它会生成一个最小 DOM 更新操作集,Vue 只对比中发生变化的部分并更新这些变化,而不是重新渲染整个页面。具体包括以下几种情况:

  • 新增节点:如果新虚拟 DOM 中出现了旧虚拟 DOM 中不存在的节点,Vue 会在对应位置新增节点。
  • 删除节点:如果旧虚拟 DOM 中的节点在新虚拟 DOM 中不存在,Vue 会删除对应的真实 DOM 节点。
  • 更新节点:如果新旧虚拟 DOM 中的节点相同,但内容发生了变化(如文本、属性等),Vue 会更新这个节点的内容。

6. 原理总结

        Vue 的 diff 算法本质上是通过逐层对比新旧虚拟 DOM 树,识别出变化的节点,并生成最小化的 DOM 操作来更新页面。它通过双端比较和 key 优化,使得对比过程高效,并避免不必要的 DOM 操作。这种算法在保持良好的用户体验的同时,最大限度地减少了性能开销。


相关文章:

  • 9.8通宵速通javascript
  • 图论(2)
  • 微信小程序uniappvue3版本-控制tabbar某一个的显示与隐藏
  • jmeter之ForEach控制器使用
  • Java | Leetcode Java题解之第386题字典序排数
  • 高压挑战:新能源汽车换电连接器的技术革新
  • 【机器人工具箱Robotics Toolbox开发笔记(十九)】机器人工具箱Link类函数参数说明
  • 时间同步服务
  • 基于yolov8的焊缝质量好坏系统python源码+onnx模型+评估指标曲线+精美GUI界面
  • JavaScript 知识点总结
  • [数据集][目标检测]鲜花检测数据集VOC+YOLO格式25215张106类别
  • 哪些无线通信系统没用OFDM系统
  • 怎么利用NodeJS发送视频短信
  • 百度飞浆OCR半自动标注软件OCRLabel配置【详细
  • 【Python篇】PyQt5 超详细教程——由入门到精通(终篇)
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • ES6简单总结(搭配简单的讲解和小案例)
  • LintCode 31. partitionArray 数组划分
  • mysql中InnoDB引擎中页的概念
  • Python实现BT种子转化为磁力链接【实战】
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Spring-boot 启动时碰到的错误
  • V4L2视频输入框架概述
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 基于axios的vue插件,让http请求更简单
  • 京东美团研发面经
  • 开发基于以太坊智能合约的DApp
  • 温故知新之javascript面向对象
  • ​iOS实时查看App运行日志
  • !!java web学习笔记(一到五)
  • # centos7下FFmpeg环境部署记录
  • #数据结构 笔记一
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (附源码)计算机毕业设计大学生兼职系统
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)http协议
  • (转)Sql Server 保留几位小数的两种做法
  • (转载)Google Chrome调试JS
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .htaccess配置常用技巧
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET Framework 3.5安装教程
  • .net framework 4.8 开发windows系统服务
  • .net 连接达梦数据库开发环境部署
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案
  • .NET 指南:抽象化实现的基类
  • .NET4.0并行计算技术基础(1)
  • .NET6 命令行启动及发布单个Exe文件
  • .NET微信公众号开发-2.0创建自定义菜单
  • //usr/lib/libgdal.so.20:对‘sqlite3_column_table_name’未定义的引用
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?