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

vue-vue2和vue3的diff算法

核心要点

  • 数据变化时,vue如何更新节点
  • 虚拟DOM 和 真实DOM 的区别
  • vue2 diff 算法
  • vue3 diff 算法

一、 数据变化时,vue如何更新节点

首先渲染真实DOM的开销是很大,比如有时候我们修改了某个数据且修改的数据量很大时,此时会频繁的操作真实dom,会不断的引起整个dom树的重绘和重排;vue是根据真实DOM生成一颗 虚拟DOM,当 虚拟DOM 某个节点的数据改变后会生成一个新的newVnode,然后newVnode和oldVnode作对比,发现有不一样的地方就直接修改在真实的DOM上

二、虚拟DOM 和 真实DOM 的区别

虚拟DOM是将真实的DOM的数据抽取出来,以对象的形式模拟树形结构;

//真实DOM
<div><p>123</p>
</div>//虚拟DOM
var Vnode = {tag: 'div',children: [{ tag: 'p', text: '123' }]
};

三、vue2 diff 算法

核心原理

  • 深度优先,同层比较,时间复杂度只有 O(n);
  • 双针比较,新头与旧头比较,新尾与旧尾比较,旧头与新尾比较,新头与旧尾比较

diff算法流程

(1)diff算法是发生在更新的过程,而更新的情况有以下几种情况

  • 老的是Text,新的是Text,直接更新
  • 老的是Array,新的是Text,把旧的全部删掉,更新为Text
  • 老的是Text,新的是Array,删掉旧的文本,更新为新的Array元素
  • 老的是Array,新的是Array,调用updateChildren函数比较子节点,这是diff的核心

(2)老的是Array,新的是Array的情况下,调用updateChildren函数,diff核心流程

  • 新旧节点VNode节点如下图所示
    在这里插入图片描述
  • 循环遍历节点
    ① 情况:当新老 VNode 节点的 start 满足 sameVnode 时,直接 patchVnode 即可,同时新老 VNode 节点的开始索引都加 1
    if (sameVnode(oldStartVnode, newStartVnode)) {patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)oldStartVnode = oldCh[++oldStartIdx]newStartVnode = newCh[++newStartIdx]
    }
    
    ② 情况:当新老 VNode 节点的 end 满足 sameVnode 时,同样直接 patchVnode 即可,同时新老 VNode 节点的结束索引都减 1
    else if (sameVnode(oldEndVnode, newEndVnode)) {patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)oldEndVnode = oldCh[--oldEndIdx]newEndVnode = newCh[--newEndIdx]
    }
    
    ③ 情况:当老 VNode 节点的 start 和新 VNode 节点的 end 满足 sameVnode 时,这说明这次数据更新后 oldStartVnode 已经跑到了 oldEndVnode 后面去了。这时候在 patchVnode 后,还需要将当前真实 dom 节点移动到 oldEndVnode 的后面,同时老 VNode 节点开始索引加 1,新 VNode 节点的结束索引减 1
    else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved rightpatchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))oldStartVnode = oldCh[++oldStartIdx]newEndVnode = newCh[--newEndIdx]
    }
    
    ④ 情况:当老 VNode 节点的 end 和新 VNode 节点的 start 满足 sameVnode 时,这说明这次数据更新后 oldEndVnode 跑到了 oldStartVnode 的前面去了。这时候在 patchVnode 后,还需要将当前真实 dom 节点移动到 oldStartVnode 的前面,同时老 VNode 节点结束索引减 1,新 VNode 节点的开始索引加 1。
    else if (sameVnode(oldEndVnode, newStartVnode)) {  // Vnode moved leftpatchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);oldEndVnode = oldCh[--oldEndIdx];newStartVnode = newCh[++newStartIdx];
    }
    
    ⑤ 以上都不满足的情况:如果新旧子节点都存在key,那么会根据oldVnode的key生成一张hash表,用当前新节点,暂时称为S的key与hash表做匹配,匹配成功就判断S和匹配节点是否为sameNode,如果是,就在真实dom中将成功的节点移到最前面,否则,将S生成对应的节点插入到dom中对应的oldS位置,S指针向中间移动,被匹配old中的节点置为undefined。如果没有key,则直接将S生成新的节点插入真实DOM(ps:这下可以解释为什么v-for的时候需要设置key了,如果没有key那么就只会做四种匹配,就算指针中间有可复用的节点都不能被复用了)

四、vue3 diff 算法

核心原理

  • 深度优先,同层比较,时间复杂度只有 O(n);
  • 双端对比算法:先看左侧,看完左侧看右侧,然后锁定中间乱序的部分
  • 最长递增子序列:针对中间乱序部分,采用最长递增子序列的算法,计算出乱序部分可以复用的最长连续节点

diff算法流程

(1)diff算法是发生在更新的过程,而更新的情况有以下几种情况

  • 老的是Text,新的是Text,直接更新
  • 老的是Array,新的是Text,把旧的全部删掉,更新为Text
  • 老的是Text,新的是Array,删掉旧的文本,更新为新的Array元素
  • 老的是Array,新的是Array,调用updateChildren函数比较子节点,这是diff的核心

(2)老的是Array,新的是Array的情况下,调用updateChildren函数,diff核心流程

  • 先处理左侧,先从左侧开始进行对比,很明显左侧的A、B都是相同的,然后锁定左侧相同的部分,处理右侧乱序部分

    在这里插入图片描述

  • 再处理右侧,从右侧开始对比,很明显右侧的B、C都是相同的,然后锁定右侧相同部分,处理左侧乱序部分

    在这里插入图片描述

  • 若新的比老的长,创建,可以看到下图新的比老的多,新的多了一个D,多出来的这个节点就需要创建并添加到尾部

    在这里插入图片描述

  • 老的比新的长,删除,可以看到下图老的比新的多了个C,多出来的这个节点需要删除

    在这里插入图片描述

  • 乱序部分,采用最长递增子序列的算法,最大递增子序列的作用就是通过新旧节点变化前后的映射,创建一个递增数组,这样就可以知道哪些节点在变化前后相对位置没有发生变化,哪些节点需要进行移动,如下图计算出E、F、Y、J 是不需要操作的节点,直接复用,然后移动K节点,即可完成一次更新;关于最长递增子序列的算法参考视频,算法核心:动态规划+二分法实现+驱节点向前(回溯) 的方式,实现了O(n logn)的时间复杂度查找

    在这里插入图片描述

参考文章

  • Vue2、Vue3的diff对比
  • 根据大崔哥的mini-vue来理解vue3中的diff算法
  • 手写Vue3框架教程(核心原理、组件渲染、diff算法、生命周期…)

相关文章:

vue-vue2和vue3的diff算法

核心要点 数据变化时&#xff0c;vue如何更新节点虚拟DOM 和 真实DOM 的区别vue2 diff 算法vue3 diff 算法 一、 数据变化时&#xff0c;vue如何更新节点 首先渲染真实DOM的开销是很大&#xff0c;比如有时候我们修改了某个数据且修改的数据量很大时&#xff0c;此时会频繁的…...

一文解读基于PaddleSeg的钢筋长度超限监控方案

项目背景 钢铁厂生产钢筋的过程中会存在部分钢筋长度超限的问题&#xff0c;如果不进行处理&#xff0c;容易造成机械臂损伤。因此&#xff0c;需要通过质检流程&#xff0c;筛选出存在长度超限问题的钢筋批次&#xff0c;并进行预警。传统的处理方式是人工核查&#xff0c;该方…...

NumPy 数组学习手册:1~5

原文&#xff1a;Learning NumPy Array 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 一、NumPy 入门 让我们开始吧。 我们将在不同的操作系统上安装 NumPy 和相关软件&#xff0c;并查看一些使用 NumPy 的简单代码。 正如“序言”所述&#xff0c;SciPy 与 NumPy 密…...

【C++11】晦涩难懂语法系列:可变参数模板

目录 可变参数模板 1.1 概念 1.2 可变参数模板定义 1.3 参数包的展开方式 1.3.1 递归展开参数包 1.3.2 逗号表达式展开参数包 1.4 STL的emplace系列函数 可变参数模板 1.1 概念 在C语言阶段&#xff0c;我们已经接触过可变参数&#xff0c;比如scand、printf等等 这里…...

计算机组成原理第二章——数据的表示与运算(下)

提示&#xff1a;时光清浅处 一步一安然 文章目录 前言2.3.1 浮点数的表示2.3.2 IEEE7542.2.3 浮点数的运算 前言 本节主要讲三个问题&#xff0c;浮点数的表示&#xff0c;IEEE 754标准&#xff0c;浮点数的加减运算 2.3.1 浮点数的表示 浮点数的作用和基本原理 定点数可表…...

1.mybatis-plus入门及使用

1.什么是MybatisPlus MyBatis-Plus 官网 为什么要学MybatisPlus&#xff1f; MybatisPlus可以节省大量时间&#xff0c;所有的CRUD代码都可以自动化完成MyBatis-Plus是一个MyBatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效…...

JavaWeb开发 —— 前端工程化

目录 一、前后端分离开发 二、YApi 三、前端工程化 1. 环境准备&#xff1a;vue-cli 2. Vue项目创建 四、Vue项目开发流程 一、前后端分离开发 ① 最早的前端开发就是实现页面&#xff0c;顶多再写写JS让页面可以有交互的特效。属于前后端未分离的时代。 早期前后端混合开…...

listener监听器框架

监听器是Web开发中常用的一种组件&#xff0c;用于监听某些事件并根据事件触发相应的处理逻辑。在Spring Boot中使用监听器可以方便地实现对程序中各种事件的监听&#xff0c;比如启动事件、关闭事件等。 首先需要定义一个监听器&#xff0c;通常需要实现ApplicationListener接…...

tp5实现导入excel表到数据库

hello&#xff0c;大家好&#xff0c;好长时间没有更新文章了。最近一直在忙着做项目。所以断更了。 那么好&#xff0c;各位老铁是否想要实现导入导出的功能 请关注我&#xff0c;解密如何实现导入导出&#xff0c; 那么今天先来讲一下用thinkphp5.0 如何实现Excel表格导入数据…...

Python基础-04 字符串

字符串的表示方式 在Python中,可以使用一对单引号/双引号或者一对三个双引号/一对三个单引号表示字符串 a hello b "hello" c hello d """hello""" # 如果字符串里面还有双引号,外面就可以使用单引号 # 反之一样 # 如果字符串里…...

VVC之编码结构

VVC之编码结构&#xff08;新一代通用视频编码的读书笔记&#xff09; 缩写概述EncAppmain函数解读 缩写 缩写含义CVSCoded Video Sequence, 编码视频序列IRAPIntra Random Access Point, 帧内随机接入点GDRGradual Decoding Refresh, 逐渐解码刷新AUAccess Unit, 访问单元PUP…...

FPGA基于SFP光口实现10G万兆网UDP通信 10G Ethernet Subsystem替代网络PHY芯片 提供工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、详细设计方案4、vivado工程详解5、上板调试验证并演示6、福利&#xff1a;工程代码的获取 1、前言 目前网上的fpga实现udp基本生态如下&#xff1a; 1&#xff1a;verilog编写的udp收发器&#xff0c;但不带ping功能&#xff0c;这样的代…...

Linux Redis主从复制 | 哨兵监控模式 | 集群搭建 | 超详细

Linux Redis主从复制 | 哨兵监控模式 | 集群搭建 | 超详细 一 Redis的主从复制二 主从复制的作用三 主从复制的流程四 主从复制实验4.1 环境部署4.2 安装Redis&#xff08;主从服务器&#xff09;4.3 修改Master节点Redis配置文件 (192.168.163.100)4.4 修改Slave节点Redis配置…...

整柜海运到美国的规格和收费标准是什么

整柜海运是指将所有货物安装在一个整箱内&#xff0c;由发货人和收货人共同操作&#xff0c;而目的港的收货人一般只有一个&#xff0c;方便操作。整柜海运到美国的主要流程有以下几个步骤&#xff1a;订舱、装柜、报关、海运、清关、提柜和送货。实际上&#xff0c;国际物流出…...

Session和Cookie区别介绍+面试题

Session 会话&#xff1a; 对应的英文单词&#xff1a;session用户打开浏览器&#xff0c;进行一系列操作&#xff0c;然后关闭浏览器。整个过程叫做一次会话一个会话包含多次请求 session机制属于B/S结构的一部分&#xff0c;主要的作用就是为了保存会话状态。(用户登录成功后…...

easyx

普通的画线图什么的 首先我们需要安装一个easyx的图形库&#xff0c;然后把头文件搞出来 #include <stdio.h> #include <easyx.h>//easyx画线啥啥的图形库 #include <graphics.h> #include <math.h> #include <conio.h>//键盘操作的头文件 设…...

记一次科学

华为云与Centos8 华为云99元Hongkong的服务器&#xff1a;1M&#xff0c;1C&#xff0c;2G&#xff0c;40G&#xff0c;自带不可更改的Centos 8.2 64bit 华为yum源不可以&#xff0c;网上找了可用的CentOS8 官方源不支持后配置yum源 # 备份 mv /etc/yum.repos.d/CentOS-Base…...

亚马逊被人差评了怎么办?

第一种&#xff1a; 也是最简单的做法就是通过电话或者邮件联系留差评的买家&#xff0c;大致意思就是按照货值的2-3倍作为赔偿&#xff0c;能不能把差评给删了 赔偿一个普通产品2-3倍的价格比起找服务商删一个差评几百到一千不等可以说是绰绰有余了&#xff0c;碰到那种愿意…...

【目标检测】YOLOv5:修改自己的网络结构

前言 YOLOv5就像一座金矿&#xff0c;里面有无数可以学习的东西。之前的博文一直将YOLOv5当作一个黑盒使用&#xff0c;只考虑模型的输入和输出&#xff0c;以此来对模型进行二次开发。 本篇博文将更近一层&#xff0c;深入到“金矿”内部&#xff0c;来尝试对模型结构进行替换…...

spring boot 工程整合mongodb,遇到的坑

首先说一下背景&#xff0c;因为其他的一个web工程有使用mongo&#xff0c;我想着给另外一个工程把mongo也加过来吧。也是最近做一个发送 丘比特信 的需求&#xff0c;觉得这个信应该是存到 mongodb。结果拿过来遇到了很大的坑&#xff0c;也是对版本对原理不了解吧。 下面介…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...