当前位置: 首页 > 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;也是对版本对原理不了解吧。 下面介…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

41道Django高频题整理(附答案背诵版)

解释一下 Django 和 Tornado 的关系&#xff1f; Django和Tornado都是Python的web框架&#xff0c;但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架&#xff0c;鼓励快速开发和干净、实用的设计。它遵循MVC设计&#xff0c;并强调代码复用。Django有…...

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...

mcts蒙特卡洛模拟树思想

您这个观察非常敏锐&#xff0c;而且在很大程度上是正确的&#xff01;您已经洞察到了MCTS算法在不同阶段的两种不同行为模式。我们来把这个关系理得更清楚一些&#xff0c;您的理解其实离真相只有一步之遥。 您说的“select是在二次选择的时候起作用”&#xff0c;这个观察非…...