diff算法_vue源码解读 diff算法

导语 最近碰到部分业务场景,代码逻辑需要了解"数组变更后,具体变更了哪一些元素,以及变更的位置.."。于是仔细研究并覆写了一遍针对数组变化的diff算法,在这里做下diff算法的逻辑分享&&源码解读

一.介绍前的准备工作

我们先了解diff方法的运行规则和前提方法.

1.虚拟node进行深度优先 && 同级对比

深度优先:

fbb9596d9b9bb5505e357aabe0f08ec8.png

同级对比

04ae780ad0ff949f1ba83641a4ceb24d.png

如上面图所示:

每次vnode都是执行同级对比(对应dom同一个父元素)

代码逻辑如下图:

bc6b83c0d526886190ae99d3f4cc9853.png

2.简单判断

sameVnode函数用来进行判断是否是同一个vnode元素。

源代码:

b645a289b8491c618302b8b7a25c6487.png

如图所示:

7a727b67be54ed6dbd3066d6a12bff85.png

这里有两个重要元素:

key : 开发者定义的”:key”

sel: 元素tagName+元素id+元素class

sel的定义源码如下:

74d12bca68addaed6786d1e0fc39cb8e.png

vNode构建函数:

f558f5b0520550cda566a0e58e82391b.png

3.构建索引

c1018c272c549737db351fd5828173b4.png

逻辑如图:

10a16a517bc601a1633ddd6a5221ecaf.png

二.如何处理元素

尽量不新增/删除dom,如图下所示:

d6bba20bb32712eab25ac89f10fb9b99.png

如果是相同vnode,源码如下:

4b595d29b6f57db5734bb43b64affd45.png

三.开始比较

1.首先会进行时间复杂度 O(n)的while循环,循环条件为 "遍历旧节点数组&&遍历新节点数组,谁先遍历完循环就结束" ,源码如下图:

cc2758a6212ea2022e3ff35c8b01d6d9.png

在每次的循环过程中,会有两大类判断方法:

1-1.首尾比较 && 首尾序号

5477d43e7e8a692ca42e6f0cd6c204fd.png

逻辑:如图上所示,首先在循环遍历前 标记好新,旧节点数组的开始位置和结束位置的序号:oldStartIdx、oldEndIdx、newStartIdx、newEndIdx;其次在循环遍历的过程中采用 "首首比较,尾尾比较,首尾比较";

源码如下:

6414e3c123564ca80a48b1004095ef42.png

如果数据为图上所示,那么根据首尾比较方法会有如下图所示结果,最终全部执行了更新操作:

72916b0e0562c3c3d35548be3f8de94f.png

1-2.索引比较 -- 最坏情况,这里的时间复杂度也是O(n),即整个算法复杂度O(n)+O(n)

每次遍历的过程中可能存在"新数组节点新增/旧数组节点删除",那么前后对比就满足不了条件。这里逻辑会进入索引比较;

比如这种情况:

75267f4f49c9e91d5cb3725e72cd7e89.png

那么,循环中会执行一遍 创建旧数组的索引对象。

那么从创建到比较的整个逻辑图如下:

7bdf554b2981d037882379bce5060be8.png

这里的源码如下:

3bfaf29fe0cdc84266d3b83c5aacfa3a.png

1-2.1 当旧节点不存在新增的节点时,进行当前oldStartIdx位置的添加:

3faf6924a6274f999b1960a08d06e3aa.png

源码如下:

cdbe6fc03301f19eb43f05e391043496.png

1-2.2 当旧数组存在节点,那么进行位置移动:

83e4cf82faa1ecfacc9f6d94a347d699.png

源码:

c5785412058ecabb0e9b9b0e10c8b683.png

1.3 当节点遍历完之后:

会存在两种情况,“新数组已经遍历完,但旧数组没有遍历完成” || “旧数组遍历完成,但新数组没有遍历完成”.

故源代码的判断如下:

f761273b32090f6a48acf920e8d38f8a.png

1.3.1 旧数组没有循环完成:

旧数组没有循环完成的效果如下图所示:

76781b338b51d3b1d30b1d71803a53ab.png

这里注意一个点,我们每次的节点更新会移动序号,即使被删除的节点不在一块 最终也会被 首尾比较算法 "摞在一块" 即 (oldStartIdx~oldEndIdx)。上图所示更加明显一些。

源码在这里就进行批量删除:

90794e089e50278042d2538f46da6d12.png

1.3.2 新数组没有循环完成:

效果如下图所示:

e84dddaf57b6dd4351e6d968d7374394.png

经过 前后对比&&索引 的过滤后,只会存在 新.末尾节点!==旧节点 及之前的连续的新节点(!==旧节点);

所以这里也被 "摞在一块" ,即 (newStartIdx~newEndIdx)

源码如下:

61f087f967bbf1399db6a442952e41ca.png

这样,整个diff的对比算法就已经走完了。所以核心就是:前后对比+索引

四.关键点

关键点大概如下

68f269b57d55e05bd6fc90a5caf6ab07.png

五.vue3.0对于diff比较前的优化

vue3.0针对"无脑"patchVnode进行了过滤 -- 静态类型Vnode:

老版的源码:

535e6cd05b2ae6f41c40c8ff201d1cf1.png

这里,我们再重复下vue2.x系列的对比更新逻辑:

e601d200c31a2d29a5bf3f7c47441fd0.png

新版的vue3.0增加了 静态类型Vnode,如果是静态类型的vnode 那么直接跳过更新,修改新节点引用即可:

bcee77cdc9efe6a16527b5434657e9c5.png

备注:comment类型 目前翻到它的源码也只是更改引用,源码作者加上了一行注释:

60908cd82d9ef9653498ef3949fda6bd.png

这里再多插一句,fragment 碎片类型 为新增的vnode类型, 即:

c5605e39fbaf820bfbfbb29e9d9e0ddb.png

vue3.0的过滤判断源码如下:

0cfb3486d08099302e65a15885f71a9c.png

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

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

相关文章

Linux驱动模块编译进内核中

BQ27501驱动编译进内核 一、 驱动程序编译进内核的步骤 在 linux 内核中增加程序需要完成以下三项工作: 1. 将编写的源代码复制到 Linux 内核源代码的相应目录; 2. 在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项; 3. 在…

oracle 的进程

W000: Wnnn命名为W000,W001,W002.....,由smcO动态产生执行上述相关任务。 Pmon: Pmon后台进程负责一下的工作:进程异常终止,会话被杀掉,事务超过空闲时间,网络连接超时,将实例信息注册到监听器上,手工注册 altersystem register; Pmon进程的清…

请简述计算机硬件系统的运行过程,操作系统简述题

✔什么是操作系统?它的功能?操作系统是控制和管理计算机硬件和软件资源,合理地组织计算机工作流程以及方便用户使用计算机系统的程序的集合。功能:处理机管理,存储器管理,I/O设备管理和文件管理以及作为操作…

python闭环最短路径_最短路径算法的实现(dijskstra):Python

dijskstra最短路径算法步骤:输入:图G(V(G),E(G))有一个源顶点S和一个汇顶点t,以及对所有的边ij属于E(G)的非负边长出cij。输出:G从s到t的最短路径的长度。第0步:从对每个顶点做临时标记L开始,做法如下&…

黑群晖二合一安装不了套件_玩PT还是得安装transmission,星际蜗牛安装黑群晖制作家用NAS...

原文作者:pt老萌新To小白:黑群晖docker安装PT神器transmission——星际蜗牛安装黑群晖制作家用NAS的折腾日记写在前面:里面的技术方法不是我原创的,都是网上找的,侵删。折腾的过程记录是原创的(好像没啥原创的了)&…

Know more about Cache Buffer Handle

在之前的文章《latch free:cache buffer handles造成的SQL性能问题》中我介绍了cache buffer handle latch的一些知识,在这里我们复习一下: "当会话需要pin住buffer header时它首先要获去buffer handle,得到buffer handle的过程中首先要…

spring boot web项目_阿里技术专家带你使用Spring框架快速搭建Web工程项目

点击上方 "程序员小乐"关注, 星标或置顶一起成长 第一时间与你相约 每日英文 We all have a past. It’s how you deal with it. 每个人都有过去,只是取决于你怎么去处理。 每日掏心话 人不都是这样吗,安慰别人的时候头头是道,自己…

MySQL执行外部sql脚本文件的命令

sql脚本是包含一到多个sql命令的sql语句,我们可以将这些sql脚本放在一个文本文件中(我们称之为“sql脚本文件”),然后通过相关的命令执行这个sql脚本文件。基本步骤如下:1、创建包含sql命令的sql脚本文件 文件中包含一…

全国计算机水平考试技巧,全国计算机等级考试上机考试应试技巧

掌握好上机考试的应试技巧,可以使考生的实际水平在考试时得到充分发挥,从而取得较为理想的成绩。历次考试均有考生因为忽略了这一点,加之较为紧张的考场气氛影响了水平的发挥,致使考试成绩大大低于实际水平。因此每个考生在应试前…

git 代码回滚_能提交到远程的Git回滚

很多情况下我们需要回滚代码,最容易想到的就是git reset。但是git reset有个弱点,它是一个彻底的回滚,不能再提交给远程了,因为在提交记录里回滚点之后的记录都不见了。做一下试验,一个文件我们提交了三次之后回滚#往前…

Mysql数据库的几大优势

为什么开源社区买mysql的帐, MySQL数据库的吸引开源社区的几大特质: 客户为什么会考虑购买MySQL 企业版Enterprise Edition : 转载于:https://www.cnblogs.com/macleanoracle/archive/2013/03/19/2968208.html

python机器人算法_DBscan算法及其Python实现

DBSCAN简介:1.简介DBSCAN 算法是一种基于密度的空间聚类算法。该算法利用基于密度的聚类的概念,即要求聚类空间中的一定区域内所包含对象(点或其它空间对象)的数目不小于某一给定阀值。DBSCAN 算法的显著优点是聚类速度快且能够有效处理噪声点和发现任意…

c语言e怎么表示_来测测!这11个C语言入门基础知识你都掌握了吗?

文章字数:8400 干货指数:⭐⭐⭐⭐⭐C语言程序的结构认识用一个简单的c程序例子,介绍c语言的基本构成、格式、以及良好的书写风格,使小伙伴对c语言有个初步认识。例1:计算两个整数之和的c程序:#include main…

泰拉瑞亚服务器怎么让玩家注册,泰拉瑞亚服务器权限指令大全

; z1 o, G5 B N; k# W% L5 E) a7 _9 k. x% z* A/ \# j) U! Y2 8 Wtshock.ignore.sendtilesquare7 p3 x/ : T- {; y4 y" k7 U8 J描述: 允许客户端无限制修改地图. # I( K8 {# K$ n( 4 d命令: 无 9 g3 L. p5 G9 M; Y( E4 w. Y v5 M$ H, \/ K; M% n3 ktshock.ignore.dropb…

Oracle甲骨文8.7亿美元高价收购Eloqua

北京,2012年12月20日—— 甲骨文今天宣布,已与领先的云营销自动化和收入绩效管理软件供应商Eloqua公司(NASDAQ代码:ELOQ)达成收购协议,收购价为每股23.50美元,总额约为8.71亿美元。Eloqua的现…

Linux开启mysql远程连接的设置步骤

Mysql默认root用户只能本地访问,不能远程连接管理mysql数据库,Linux如何开启mysql远程连接?设置步骤如下: 1、GRANT命令创建远程连接mysql授权用户itlogger mysql -u root -p mysql>GRANT ALL PRIVILEGES ON *.* TO itloggerlo…

3dsmax展uv_TexTools|3dmax展UV插件(TexTools for 3ds Max)下载v4.10免费版 - 欧普软件下载

TexTools for 3ds Max是为3dmax推出的一款展UV插件,主要功能包括自动加入环形边结构、材质加速烘焙、光影追踪渲染预设、多种模型对象棋盘格贴图等,支持3dsmax或以上版本,在editUVW模式下可以展开UVW修改,编辑UVW编辑器和编辑按钮…

新浪云python示例_Python Web框架Flask中使用新浪SAE云存储实例

对于部署在新浪应用引擎SAE上的项目,使用新浪SAE云存储是不错的存储方案。 新浪SAE云存储仅能在SAE环境中正常使用,对它进行简单封装后,可以直接在Flask中使用,项目代码见GitHub上Flask-SaeStorage。 使用示例代码: fr…

hp服务器如何ghost系统,惠普(HP)电脑安装不了GHOST系统的解决办法

你还在为不知道惠普(HP)电脑安装不了GHOST系统的解决办法而不知所措么?下面来是学习啦小编为大家收集的惠普(HP)电脑安装不了GHOST系统的解决办法,欢迎大家阅读:惠普(HP)电脑安装不了GHOST系统的解决办法1、按F10进入CMOS2、找到电源设置项(Power Manag…

azm335x 串口配置

任务: 配置uart3和uart5 UART3 UART5 配置uart3 1. 修改mmu33xx.c _AM33XX_MUXENTRY(MII1_RXD3, 0, "mii1_rxd3", NULL, "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", NULL, "mcasp0_axr0", "gpio2_…