vue3的diff

以vue3的patch为例

  • 首先判断两个节点是否为相同同类节点,不同则删除重新创建
  • 如果双方都是文本则更新文本内容
  • 如果双方都是元素节点则递归更新子元素,同时更新元素属性
  • 更新子节点时又分了几种情况
    • 新的子节点是文本,老的子节点是数组则清空,并设置文本;
    • 新的子节点是文本,老的子节点是文本则直接更新文本;
    • 新的子节点是数组,老的子节点是文本则清空文本,并创建新子节点数组中的子元素;
    • 新的子节点是数组,老的子节点也是数组,那么比较两组子节点,更新细节blabla
  • vue3中引入的更新策略:静态节点标记等

vdom中diff算法的简易实现
以下代码只是帮助大家理解diff算法的原理和流程

1.将vdom转化为真实dom:

const createElement = (vnode) => {
  let tag = vnode.tag;
  let attrs = vnode.attrs || {};
  let children = vnode.children || [];
  if(!tag) {
    return null;
  }
  //创建元素
  let elem = document.createElement(tag);
  //属性
  let attrName;
  for (attrName in attrs) {
    if(attrs.hasOwnProperty(attrName)) {
      elem.setAttribute(attrName, attrs[attrName]);
    }
  }
  //子元素
  children.forEach(childVnode => {
    //给elem添加子元素
    elem.appendChild(createElement(childVnode));
  })

  //返回真实的dom元素
  return elem;
}

2.用简易diff算法做更新操作

function updateChildren(vnode, newVnode) {
  let children = vnode.children || [];
  let newChildren = newVnode.children || [];

  children.forEach((childVnode, index) => {
    let newChildVNode = newChildren[index];
    if(childVnode.tag === newChildVNode.tag) {
      //深层次对比, 递归过程
      updateChildren(childVnode, newChildVNode);
    } else {
      //替换
      replaceNode(childVnode, newChildVNode);
    }
  })
}
if(新Vdom是文本节点){
	只需要设置新的Vdom对应的真实dom的文本值就行
} else if(新Vdom不是文本节点){
	if(新Vdom有孩子 & 旧的Vdom有孩子){
		updateChildren(两者的孩子)
	} else if(){
		清空新Vdom对应的真实dom的文本值
		把新Vdom的孩子的真实dom,添加到新Vdom的真实dom内
	} else if(只是旧Vdom有孩子){
		把新Vdom的孩子的真实dom删除
	} else if(新旧都没有孩子,旧vdom有文本){
		把新Vdom的真实dom文本清空
	}
}

在这里插入图片描述

vue2 和 vue3 diff的区别

Vue.js 2 和 Vue.js 3 在 diff 算法上有一些显著的区别。让我们先来了解一下它们的 diff 算法特点和区别:

Vue.js 2 的 Diff 算法

Vue.js 2 使用的是基于虚拟 DOM 的 diff 算法,具体是采用的是著名的 “Virtual DOM” diff 算法。它的主要特点包括:

  1. 双端比较:Vue.js 2 的 diff 算法采用双端比较,即同时对新旧节点进行前后比较。这个算法的复杂度是 O(n^3),其中 n 是节点的数量。

  2. 不可中止:由于双端比较的特性,Vue.js 2 的 diff 算法不可中止,即必须对整个虚拟 DOM 树进行比较,不能在中途中断。

  3. Diff 算法细节:在比较节点时,Vue.js 2 的 diff 算法需要考虑节点的类型、属性、子节点等细节,以确定是否需要进行更新。

Vue.js 3 的 Diff 算法

Vue.js 3 引入了一个全新的 diff 算法,名为 Fast DOM,这个算法相对于 Vue.js 2 的 diff 算法有以下特点:

  1. 双端向下比较:Vue.js 3 的 diff 算法采用了双端向下比较,是一种更高效的比较方式。它减少了比较的次数,提高了 diff 的性能。

  2. 可中止:与 Vue.js 2 不同,Vue.js 3 的 diff 算法是可中止的,也就是说在比较过程中可以根据需要提前结束,从而提高了渲染性能。

  3. Patch Flag:Vue.js 3 将 diff 过程中的具体操作进行了合并和优化,采用了 Patch Flag 的策略,通过事先标记节点的类型和属性,来减少不必要的比较,从而提升性能。

区别总结

主要区别包括:

  1. 比较算法:Vue.js 2 使用双端比较的 Virtual DOM 算法,Vue.js 3 使用双端向下比较的 Fast DOM 算法。

  2. 性能表现:Vue.js 3 的新算法在性能表现上更优秀,特别是在大型应用中能够提供更好的性能。

  3. 可中止性:Vue.js 3 的 diff 算法可以在必要时中止,这是一个提高性能的重要优势。

总的来说,Vue.js 3 在 diff 算法方面的改进使得其在性能表现上有了显著的提升,特别是对于大型应用或者频繁更新的场景。

为什么Vue.js 3 的 diff 算法可以在必要时中止

Vue.js 3 的 diff 算法可以在必要时中止主要得益于其基于 Proxy 的响应式系统以及新的编译器。

在 Vue.js 3 中,使用了基于 Proxy 的响应式系统取代了 Vue.js 2 中的基于 Object.defineProperty 的响应式系统。Proxy 具有更细粒度的拦截能力,可以在访问、设置和删除属性时触发相应的拦截器函数。这使得 Vue.js 3 能够更精确地追踪应用程序状态的变化。

同时,Vue.js 3 也引入了新的编译器,它可以生成针对模板的优化代码。编译过程中,Vue.js 3 能够通过静态分析模板的结构和指令,生成与之对应的 Patch Flag。Patch Flag 是一个标记,用于在 diff 算法执行过程中快速定位需要更新的节点。

基于 Proxy 的响应式系统和新的编译器共同作用下,Vue.js 3 的 diff 算法可以利用 Patch Flag 来优化 diff 过程。通过比较节点的 Patch Flag,Vue.js 3 可以在必要时中止 diff 过程并跳过不必要的比较。这样的优化降低了 diff 的复杂性和开销,提高了渲染性能。

需要注意的是,Vue.js 3 的 diff 中止能力是有限的。当涉及到更深层次的嵌套和更新时,可能无法完全中止 diff 过程。但整体上,Vue.js 3 的 diff 算法在性能方面得到了显著的提升,特别是对于复杂的应用场景。

为什么说双端向下比较更加高效

双端比较和双端向下比较是 Vue.js 中两种不同的 diff 算法实现方式。

双端比较

在 Vue.js 2 中,采用的是双端比较的 diff 算法。这意味着每次 diff 过程会同时对新旧节点的头部和尾部进行比较。

  1. 首先,算法会比较新节点和旧节点的头部元素。根据不同的情况进行相应的处理,如元素类型不同、key 不匹配等。
  2. 接下来,算法会比较新节点和旧节点的尾部元素。同样,会根据不同情况进行相应处理。
  3. 如果头部或尾部的比较完成后,任一节点已经被处理完(新增或删除),算法会进入下一轮比较。
  4. 如果头部和尾部的比较都完成后,算法会进一步处理新旧节点之间的中间部分。

这种双端比较算法在比较的过程中可以灵活地根据新旧节点的不同情况进行处理。但由于需要同时比较头部和尾部,相比于其他比较方式可能会存在一些额外的开销。

双端向下比较

在 Vue.js 3 中,采用的是双端向下比较的 diff 算法。这意味着每次 diff 过程会从根节点开始,同时向下比较新旧节点的子节点。

  1. 首先,算法会比较根节点的新旧子节点数组,根据不同的情况进行相应处理。例如,当两个节点的头部元素相同,则直接对这两个节点的子节点数组进行比较。
  2. 如果比较完根节点的子节点数组后,任一节点已被处理完,则算法终止比较。
  3. 如果根节点的子节点数组比较完成后,算法会继续向下比较新旧节点的子节点数组,直到所有节点都被处理完。

双端向下比较的主要优势在于它可以在比较过程中进行中止。因为每次只需向下比较一个节点的子节点,如果在比较的过程中发现某个节点已被处理完,算法可以提前终止后续比较,从而减少不必要的工作量和开销。

相对于双端比较,双端向下比较可以更高效地执行 diff 算法。它通过逐层比较子节点的方式,使得算法能够更快速地中止和跳过不必要的比较。这种优化对于大型应用或者频繁更新的场景能够提供更好的性能表现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

07 STL 简介

目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…

详解AP3216C(三合一sensor: 光照、距离、照射强度)驱动开发

目录 概述 1 认识AP3216C 1.1 AP3216C特性 1.2 AP3216C内部结构 1.3 AP3216C 硬件电路 1.4 AP3216C工作时序 1.4.1 I2C 写数据协议 1.4.2 I2C 读数据协议 1.5 重要的寄存器 1.5.1 系统配置寄存器 1.5.2 和中断相关寄存器 1.5.3 IR数据寄存器 1.5.4 ALS 数据寄存器 …

Android 开发一个耳返程序(录音,实时播放)

本文目录 点击直达 Android 开发一个耳返程序程序编写1. 配置 AndroidManifast.xml2.编写耳返管理器3. 录音权限申请4. 使用注意 最后我还有一句话要说怕相思,已相思,轮到相思没处辞,眉间露一丝 Android 开发一个耳返程序 耳返程序是声音录入…

计算机网络实验八 利用 Java /C++开发网络聊天应用程序

一、实验目的和要求 1)基本掌握利用 Java 开发环境调试应用程序的方法。 2)理解基于套接字开发网络应用程序的过程,深入理解客户/服务器方式工作原理。 3)掌握基于Java和C++开发网络通信程序的方法。 二、实验环境 1)运行 Windows 2008 Server/XP/7 操作系统的 PC 2 台…

应急响应实战笔记03权限维持篇(3)

0x00 前言 攻击者在获取服务器权限后,会通过一些技巧来隐藏自己的踪迹和后门文件,本文介绍Linux下的几种隐藏技术。 0x01 隐藏文件 Linux 下创建一个隐藏文件:touch .test.txt touch 命令可以创建一个文件,文件名前面加一个 点…

一文读懂:AWS 网络对等互连(VPC peering)实用操作指南

VPC peering connection-网络对等互连在您的 Atlas VPC 和云提供商的 VPC 之间建立私有连接。该连接将流量与公共网络隔离以提高安全性。本篇文章有VPC peering的操作指南以及价格等信息。如还有疑问请联系我们MongoDB的销售,客户成功经理或解决方案架构师。 1 使用…

开源大语言模型作为 LangChain 智能体

概要 开源大型语言模型 (LLMs) 现已达到一种性能水平,使它们适合作为推动智能体工作流的推理引擎: Mixtral 甚至在我们的基准测试中 超过了 GPT-3.5,并且通过微调,其性能可以轻易的得到进一步增强。 引言 针对 因果语言建模 训练的大型语言模…

用买糖果的方式来理解正交匹配追踪(OMP)算法

在信号处理领域,压缩感知(Compressed Sensing)是一种能够从远少于传统奈奎斯特采样定理所要求的样本数目中重建稀疏信号的技术。压缩感知的理论基础在于一个前提假设,即许多自然信号都含有稀疏的表示,换句话说&#xf…

【Python】OpenCV-图像轮廓检测初学

图像轮廓检测初学 在图像处理领域中,轮廓检测是一项重要的任务,用于寻找并标定图像中的物体边缘。本文将介绍如何使用OpenCV库进行图像轮廓检测,并展示一个简单的示例代码。代码中的注释将详细解释每一步的操作。 1. 引言 图像轮廓检测是图…

决策树算法

目录 谷歌笔记本(可选) 决策树 决策树的一般流程 信息增益 划分数据集 递归构建决策树 使用Matplotlib注解绘制树形图 Matplotlib注解 构造注解树 测试和存储分类器 测试算法:使用决策树执行分类 使用算法:决策树的存…

RISC-V知识总结 —— 指令集

资源1: RISC-V China – RISC-V International 资源2: RISC-V International – RISC-V: The Open Standard RISC Instruction Set Architecture 资源3: RV32I, RV64I Instructions — riscv-isa-pages documentation 1. 指令集架构的类型 在讨论RISC-V或任何处理器架构时&…

基于springboot+vue的图书进销存管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

【Vue3】学习computed计算属性

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

华清远见嵌入式学习——驱动开发——day9

目录 作业要求: 作业答案: 代码效果: ​编辑 Platform总线驱动代码: 应用程序代码: 设备树配置: 作业要求: 通过platform总线驱动框架编写LED灯的驱动,编写应用程序测试&…

JAVA代码审计之XSS漏洞

Part1 漏洞案例demo&#xff1a; 没有java代码审计XSS漏洞拿赏金的案例。 所以将就看看demo吧 漏洞原理&#xff1a;关于XSS漏洞的漏洞原理核心其实没啥好说的&#xff0c;网上一查一大堆 反射性XSS漏洞 <% page language"java" contentType"text/html; c…

C# OpenCvSharp 利用白平衡技术进行图像修复

目录 效果 灰度世界(GrayworldWB)-白平衡算法 完美反射(SimpleWB)-白平衡算法 基于学习的(LearningBasedWB)-白平衡算法 代码 下载 C# OpenCvSharp 利用白平衡技术进行图像修复 OpenCV xphoto模块中提供了三种不同的白平衡算法&#xff0c;分别是&#xff1a;灰度世界(G…

bat脚本进程停止与启动

在Windows操作系统中&#xff0c;批处理&#xff08;Batch&#xff09;脚本是一种常见的自动化脚本工具&#xff0c;通过BAT文件来执行一系列DOS命令。通过BAT脚本&#xff0c;我们可以轻松地控制进程的启动和停止。 一、进程停止 在BAT脚本中&#xff0c;要停止一个进程&…

基于Redis限流(固定窗口、滑动窗口、漏桶、令牌桶)(肝货!!!)

近期redis复习的比较多&#xff0c;在限流这方面发现好像之前理解的限流算法有问题&#xff0c;索性花了一天“带薪摸鱼”时间肝了一天&#xff0c;有问题可以评论区探讨。 废话不多说&#xff0c;正片开始 目录 Maven固定窗口滑动窗口算法漏桶算法令牌桶算法 Maven 有些不用的…

B树的介绍

R-B Tree 简介特性B树特性m阶B树的性质&#xff08;这些性质是B树规定的&#xff09; B树的搜索B树的添加B树的删除——非叶子结点 简介 R-B Tree又称为Red-Black Tree&#xff0c;红黑树。是一种特殊的二叉查找树&#xff0c;红黑树的每个节点上都有存储为表示结点的颜色&…

3-Bean的生命周期

Bean的生命周期 创建对象和初始化是在AbstractAutowireCapableBeanFactory.doCreateBean()中完成的 创建对象 实例化&#xff08;构造方法&#xff09;依赖注入 初始化 执行Aware接口回调执行BeanPostProcessor.postProcessBeforeInitialization执行InitializingBean回调&…