Vue 3 Diff 算法过程及基本实现方式

Vue 3 的 Diff 算法

Vue 3 使用的是一种高效的 DOM Diff 算法,主要用于在虚拟 DOM 树发生变化时,计算最小的操作以更新真实 DOM。相比 Vue 2,Vue 3 的 Diff 算法做了很多优化。


Diff 算法的背景与目的

  • 虚拟 DOM 树的对比:在 Vue 中,每次组件状态更新时,会生成一个新的虚拟 DOM 树,Diff 算法会对新旧虚拟 DOM 树进行对比,计算需要更新的部分。
  • 更新真实 DOM:根据 Diff 的结果,Vue 仅对必要的部分执行 DOM 更新,避免全量重建,提高性能。

Vue 3 Diff 算法的核心逻辑

Vue 3 的 Diff 算法采用了一种 双端比较策略,与 Vue 2 的简单逐个比较方式不同,其性能更高。

算法流程
  1. 双端指针(双端 Diff)

    • Vue 3 使用左右双指针同时扫描新旧节点列表:
      • 头指针从左向右。
      • 尾指针从右向左。
    • 优化了只从左到右逐个比较的逻辑,适应更多场景。
  2. 比较规则

    • 优先匹配相同节点
      • 比较当前头指针的节点,如果相同则直接复用。
      • 如果头尾对比都无法找到相同节点,则可能需要移动或创建节点。
    • 最长递增子序列(LIS)优化
      • 用于处理中间乱序的节点,最小化移动操作。
  3. 四种主要比较情况

    • 头与头比较(旧头与新头):
      • 如果匹配,移动头指针,继续下一轮比较。
    • 尾与尾比较(旧尾与新尾):
      • 如果匹配,移动尾指针,继续下一轮比较。
    • 旧头与新尾比较(优化尾部插入的情况):
      • 如果匹配,说明节点从头移动到了尾,调整位置后继续。
    • 旧尾与新头比较(优化头部插入的情况):
      • 如果匹配,说明节点从尾移动到了头,调整位置后继续。
  4. 中间部分的乱序处理

    • 当头尾指针交错后,剩余的节点(乱序部分)需要特殊处理。
    • Vue 3 使用 最长递增子序列(LIS)算法 找出新列表中可以复用的最长子序列。
      • 其余节点要么插入,要么删除。
    • 最小化 DOM 操作次数,提升性能。

Vue 3 Diff 算法的优化点

  1. 双端比较

    • 同时从两端扫描新旧虚拟 DOM 节点列表,减少无效比较。
  2. 最长递增子序列(LIS)

    • 在处理乱序部分时,通过 LIS 算法最小化 DOM 移动操作。
  3. Patch 标记

    • Vue 3 在生成虚拟 DOM 时,对每个节点添加了 动态标记,用于标识哪些部分需要更新、复用或跳过,从而减少无用的计算。
  4. 静态节点的静态提升

    • 对不变的静态节点进行提升,只计算一次,避免重复对比。
  5. Fragment 支持

    • 允许多个子节点共存(不需要唯一根节点),简化 DOM 结构的操作。

Diff 算法的运行时复杂度

  • 最优情况(双端快速匹配):O(n)
  • 普通情况(中间乱序部分 + LIS):O(n + m),其中 n 是节点数量,m 是 LIS 的计算复杂度。
  • 最坏情况(无任何匹配):O(n^2),但在实际场景中几乎不会发生。

伪代码示例

以下是 Vue 3 Diff 核心逻辑的简化伪代码:

function diff(oldChildren, newChildren) {let oldStart = 0, oldEnd = oldChildren.length - 1;let newStart = 0, newEnd = newChildren.length - 1;while (oldStart <= oldEnd && newStart <= newEnd) {if (oldChildren[oldStart] === newChildren[newStart]) {// 头与头匹配patch(oldChildren[oldStart], newChildren[newStart]);oldStart++;newStart++;} else if (oldChildren[oldEnd] === newChildren[newEnd]) {// 尾与尾匹配patch(oldChildren[oldEnd], newChildren[newEnd]);oldEnd--;newEnd--;} else if (oldChildren[oldStart] === newChildren[newEnd]) {// 旧头与新尾匹配move(oldChildren[oldStart], newEnd);oldStart++;newEnd--;} else if (oldChildren[oldEnd] === newChildren[newStart]) {// 旧尾与新头匹配move(oldChildren[oldEnd], newStart);oldEnd--;newStart++;} else {// 中间乱序部分处理handleUnmatched(oldChildren, newChildren, oldStart, oldEnd, newStart, newEnd);}}// 剩余节点的插入或删除handleRemaining(oldChildren, newChildren, oldStart, oldEnd, newStart, newEnd);
}

总结

Vue 3 的 Diff 算法通过以下方式提升性能:

  • 双端比较优化。
  • 利用最长递增子序列(LIS)减少 DOM 操作。
  • 静态提升减少重复计算。
  • 更高效地处理 Fragment。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/66846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dependency check 通过Maven构建时,配置Mysql数据库遇到的三个坑

使用过Dependency check的同学&#xff0c;一定会遇到这个问题—— 每次执行依赖扫描时&#xff0c;由于网络问题会导致NVD下载种子数据的过程中的种种失败&#xff0c;不仅浪费了大量时间&#xff0c;还会因为下载文件的不完整性直接导致依赖检测的失败。所以我在使用Dependen…

【面试题】技术场景 5、日志采集ELK

日志采集的重要性与采集方式 重要性&#xff1a;在项目开发、测试及生产环境中&#xff0c;日志是定位系统问题的关键手段&#xff0c;对系统维护与问题排查至关重要。采集方式 常规采集&#xff1a;按天保存日志文件至专门目录&#xff0c;文件名包含项目名、端口及日期&…

【数据库】三、SQL语言

文章目录 三、SQL语言1 概述2 数据定义(DDL)2.1 定义数据库2.2 定义基本表2.3 修改基本表2.4 删除基本表 3 数据操作(DML)3.1 数据查询3.1.1 单表查询3.1.2 连接查询3.1.3 嵌套查询3.1.4 集合查询 3.2 数据更新3.2.1 插入数据3.2.2 修改数据3.2.3 删除数据 4 数据控制(DCL)5 视…

Unity中 Xlua使用整理(二)

1.Xlua的配置应用 xLua所有的配置都支持三种方式&#xff1a;打标签&#xff1b;静态列表&#xff1b;动态列表。配置要求&#xff1a; 列表方式均必须是static的字段/属性 列表方式均必须放到一个static类 建议不用标签方式 建议列表方式配置放Editor目录&#xff08;如果是H…

Python Matplotlib教程-Matplotlib 多子图布局

Python Matplotlib 多子图布局 Matplotlib 是 Python 中最常用的数据可视化库&#xff0c;它提供了强大的功能来绘制不同类型的图表。在实际应用中&#xff0c;通常需要将多个图表绘制在同一个画布上&#xff0c;这就需要用到 多子图布局。本篇文章将详细介绍如何使用 Matplot…

全方位解读消息队列:原理、优势、实例与实践要点

全方位解读消息队列&#xff1a;原理、优势、实例与实践要点 一、消息队列基础认知 在数字化转型浪潮下&#xff0c;分布式系统架构愈发复杂&#xff0c;消息队列成为其中关键一环。不妨把消息队列想象成一个超级“信息驿站”&#xff0c;在古代&#xff0c;各地的信件、物资运…

Photon最新版本PUN 2.29 PREE,在无网的局域网下,无法连接自己搭建的本地服务器

1.图1为官方解答 2.就是加上这一段段代码&#xff1a;PhotonNetwork.NetworkingClient.SerializationProtocol SerializationProtocol.GpBinaryV16; 完美解决 unity 商店最新PUN 2 插件 不能连接 &#xff08;环境为&#xff1a;本地局域网 无外网情况 &#xff09; …

消息中间件类型介绍

消息中间件是一种在分布式系统中用于实现消息传递的软件架构模式。它能够在不同的系统或应用之间异步地传输数据&#xff0c;实现系统的解耦、提高系统的可扩展性和可靠性。以下是几种常见的消息中间件类型及其介绍&#xff1a; 1.RabbitMQ 特点&#xff1a; • 基于AMQP&#…

51单片机(二)中断系统与外部中断实验

中断即单片机因为某些原因E暂定现在的工作P0&#xff0c;转去做其他的工作P1&#xff0c;完了之后继续之前的事P0&#xff0c;其他工作P1就是中断程序&#xff0c;原因E就是中断事件&#xff0c;原因由外部发生&#xff0c;程序不能预测到的是硬中断&#xff0c;可以由程度触发…

python-42-使用selenium-wire爬取微信公众号下的所有文章列表

文章目录 1 seleniumwire1.1 selenium-wire简介1.2 获取请求和响应信息2 操作2.1 自动获取token和cookie和agent2.3 获取所有清单3 异常解决3.1 请求url失败的问题3.2 访问链接不安全的问题4 参考附录1 seleniumwire Selenium WebDriver本身并不直接提供获取HTTP请求头(header…

汽车信息安全 -- S32K1如何更新BOOT_MAC

目录 1.安全启动模式回顾 2.为什么要讨论BOOT_MAC 3.S32K1如何更新? 1.安全启动模式回顾 之前提到过,S32K1系列提供了Crypto Service Engine硬件加密模块(简称CSEc),大家可以通过该芯片系统寄存器SDID.FEATURES(System Device Identification Register)来判断自己的片子…

【Python】Python与C的区别

文章目录 语句结束符代码块表示变量声明函数定义注释格式Python的标识符数据输入input()函数数据输出print()函数 语句结束符 C 语言 C 语言中每条语句必须以分号;结束。例如&#xff0c;int a 10;、printf("Hello, World!");。分号是语句的一部分&#xff0c;用于…

理解Unity脚本编译过程:程序集

https://docs.unity3d.com/Manual/script-compilation.html 关于Unity C#脚本编译的细节&#xff0c;其中一个比较重要的知识点就是如何自定义Assembly。 预定义的assembly 默认情况下&#xff0c;Unity会按照这个规则进行编译。 PhaseAssembly nameScript files1Assembly-…

Linux内核TTY子系统有什么(6)

接前一篇文章&#xff1a;Linux内核TTY子系统有什么&#xff08;5&#xff09; 本文内容参考&#xff1a; Linux TTY子系统框架-CSDN博客 一文彻底讲清Linux tty子系统架构及编程实例-CSDN博客 linux TTY子系统(3) - tty driver_sys tty device driver-CSDN博客 Linux TTY …

《代码随想录》Day31打卡!

《代码随想录》贪心算法&#xff1a;合并区间 本题的完整题目如下所示&#xff1a; 本题的完整思路如下所示&#xff1a; 1.本题依然是先对数组的左边界进行排序。将数组的第一个元素赋值给current。 2.遍历数组&#xff0c;判断current中的右边界和当前元素的左边界是否有重叠…

KL 散度:多维度解读概率分布间的隐秘 “距离”

深入理解KL散度&#xff1a;从多维度全面剖析 损失函数相关文章&#xff08;置顶&#xff09; 1. KL 散度&#xff1a;多维度解读概率分布间的隐秘 “距离” 2. 熵与交叉熵&#xff1a;从不确定性角度理解 KL 散度 3. 机器学习、深度学习关于熵你所需要知道的一切 引言 KL散即…

node-sass@4.14.1报错的最终解决方案分享

输入npm i全安装文件所需的依赖的时候&#xff0c;博主是使用sass去书写的&#xff0c;使用的是node-sass4.14.1和sass-loader7.3.1的版本的&#xff0c;安装的时候老是出现错误&#xff0c; node-sass4.14.1版本不再被支持的原因 node-sass 是一个基于 LibSass 的 Node.js 绑…

设计模式(观察者模式)

设计模式&#xff08;观察者模式&#xff09; 第三章 设计模式之观察者模式 观察者模式介绍 观察者模式&#xff08;Observer Design Pattern&#xff09; 也被称为发布订阅模式 。模式定义&#xff1a;在对象之间定义一个一对多的依赖&#xff0c;当一个对象状态改变的时候…

PyCharm 的安装与使用(Window)

1 PyCharm 简介 PyCharm 是一款由 JetBrains 公司开发的专门用于 Python 语言开发的集成开发环境&#xff08;IDE&#xff09;。以下是其相关介绍&#xff1a; 1.1 特点与功能 智能代码编辑&#xff1a;提供高度智能化的代码编辑器&#xff0c;支持语法高亮、自动补全、代码重…