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

Vue中的diff算法

文章目录

  • diff算法是什么
  • 比较方式
  • 源码分析
    • patch
    • patchVnode
    • updateChildren
    • 小结
  • Vue3中diff算法优化

diff算法是什么

diff算法是一种通过同层的树节点进行比较的高效算法

其有两个特点:

  • 比较只会在同层级进行,不会跨层级比较
  • 在dff比较的过程中,循环从两边向中间比较(首位交叉对比

diff算法在很多场景下都有应用,在Vue中,作用于虚拟dom渲染成真实dom的新旧VNode节点比较

比较方式

diff整体策略为:深度优先,同层比较

  1. 比较只会在同层级进行,不会跨层级比较
    在这里插入图片描述
  2. 比较的过程中,循环从两边向中间收拢
    在这里插入图片描述
    下面举个vue通过diff算法更新的例子:
    新旧VNode节点如下图所示:
    在这里插入图片描述
    第一次循环后,发现旧节点D与新节点D相同,直接复用引旧节点D作为diff后的第一个真实节点,同时旧节点endIndex移动到C,新节点的startIndex移动到了C
    在这里插入图片描述
    第二次循环后,同样是旧节点的末尾和新节点的开头(都是C)相同,同理,diff后创建了C的真实节点插入到第一次创建的D节点后面。同时旧节点的endIndex移动到了B,新节点的startIndex移动到了E
    在这里插入图片描述
    第三次循环中,发现E没有找到,这时候只能直接创建新的真实节点E,插入到第二次创建的C节点之后。同时新节点的startIndex移动到了A。旧节点的startIndex和endIndex都保持不动。
    在这里插入图片描述

源码分析

当数据发生改变时,set方法会调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图
源码位置:src/core/vdom/patch.js

patch

function patch(oldVnode, vnode, hydrating, removeOnly) {if (isUndef(vnode)) { // destoryif (isDef(oldVnode)) invokeDestroyHook(oldVnode)return}let isInitialPatch = falseconst insertedVnodeQueue = []if (isUndef(oldVnode)) {isInitialPatch = truecreateElm(vnode, insertedVnodeQueue) // dom} else {const isRealElement = isDef(oldVnode.nodeType)if (!isRealElement && sameVnode(oldVnode, vnode)) {// patchVnodepatchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly)} else {// domif (isRealElement) {if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {oldVnode.removeAttribute(SSR_ATTR)hydrating = true}if (isTrue(hydrating)) {if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {invokeInsertHook(vnode, insertedVnodeQueue, true)return oldVnode}}oldVnode = emptyNodeAt(oldVnode)}return vnode.elm}}
}

patch函数前两个参数位为oldVnodeVnode,分别代表新的节点和之前的旧节点,主要做了四个判断:

  • 没有新节点,直接触发旧节点的destory钩子
  • 没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全是新建,所以只调用createElm
  • 旧节点和新节点自身一样,通过sameVnode判断节点是否一样,一样时,直接调用patchVnode去处理这两个节点
  • 旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点

patchVnode

function patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) {// 如果新旧节点一致,什么都不做if (oldVnode === vnode) {return

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 华为嵌入式面试题及参考答案(持续更新)
  • PyTorch 中的一个函数:torch.pow
  • 完美捕捉趋势!立足市场必备“指数通行红绿灯”!股票量化分析工具QTYX-V2.8.7...
  • 数据库(MySQL)-视图、存储过程、触发器
  • WPF MVVM框架:CommunityToolkit.Mvvm包使用介绍
  • 【Python】sqlite加密库pysqlcipher3编译安装步骤
  • C#/WinFrom TCP通信+ 网线插拔检测+客服端异常掉线检测
  • Linux中,MySQL的用户管理
  • 集合的面试题和五种集合的详细讲解
  • 小猪佩奇.js
  • C++图网结构算法
  • C 语言动态顺序表
  • linux系统常用命令(个人使用)
  • 深入分析 Android ContentProvider (四)
  • 《Cross-Modal Dynamic Transfer Learning for Multimodal Emotion Recognition》
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 0x05 Python数据分析,Anaconda八斩刀
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • CSS居中完全指南——构建CSS居中决策树
  • Java的Interrupt与线程中断
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Promise面试题,控制异步流程
  • React中的“虫洞”——Context
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 前端性能优化——回流与重绘
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #、%和$符号在OGNL表达式中经常出现
  • #Linux(Source Insight安装及工程建立)
  • #LLM入门|Prompt#3.3_存储_Memory
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (Ruby)Ubuntu12.04安装Rails环境
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (十)T检验-第一部分
  • (四)模仿学习-完成后台管理页面查询
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)为C# Windows服务添加安装程序
  • (转)重识new
  • (状压dp)uva 10817 Headmaster's Headache
  • ****Linux下Mysql的安装和配置
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .net 获取某一天 在当月是 第几周 函数
  • .NET 使用配置文件
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .NET面试题解析(11)-SQL语言基础及数据库基本原理
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • ??Nginx实现会话保持_Nginx会话保持与Redis的结合_Nginx实现四层负载均衡