Vue深入学习2—虚拟DOM和Diff算法

1、snabbdom 是什么?

snabbdom是“速度"的意思,源码只有200行,使用TS写的,让东西变得模块化

2、snabbdom 的 h 函数如何工作?

h函数用于产生虚拟节点,同时也可以嵌套使用,得到虚拟DOM树,

3、什么是虚拟DOM?

实际上它对真实DOM的抽象结果,是JS和真实DOM之间的一个缓存,原生DOM运行慢,将DOM放在JS层,提高渲染性能。

​ 3.1、创建一个虚拟DOM

// 真实DOM
<ul id='list'><li class='item'>Item 1</li><li class='item'>Item 2</li><li class='item'>Item 3</li>
</ul>
// 虚拟DOMvar element = {tagName: 'ul', // 节点标签名props: { // DOM的属性,用一个对象存储键值对id: 'list'},children: [ // 该节点的子节点{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},]}

​ 3.2、patch函数源码流程图

image-20210719192255676

// 手写patch.js
export default function(oldVnode, newVnode){// 1、判断传入的第一个参数,是DOM节点还是虚拟节点?if(oldValue.sel == '' || oldValue.sel == undefined){// 2、传入的第一个参数是DOM 节点,包装成虚拟节点oldValue = vnode(oldValue.tagName.toLowerCase(), {}, [], undefined, oldValue);}// 3、判断oldValue和newValue是否为同一节点?if(oldValue.key == newValue.kee && oldValue.sel == newValue.sel){console.log('是同一个节点');// 3.1、判断新旧vnode是否为同一个对象if(oldValue == newValue) return;// 3.2、判断新旧vnode有没有text属性if(newValue.text != undefined && (newValue.children == undefined || newValue.children.length == 0)){console.log('新vnode有text属性');// 3.2.1、如果新虚拟节点中的text和老的虚拟节点的text不同,那么直接让新的text写入老的elm中。如果老的elm中的chilren,那么也会立即消失掉。if(newValue.text != oldValue.text){oldValue.elm.innerHTML = newValue.text;}}else {// 新vnode没有text属性,有chidrenconsole.log('新的vnode没有text属性');// 3.2.2、判断老的有咩有childrenif(oldValue.children != undefined && oldVlaue.children > 0){// 3.2.2.1、老节点有childrenlet ch = newVnode.children[i];// 3.2.2.2、再次遍历,看看oldValue 中有没有节点和他是same的let isExist = false;for(let j = 0; j < oldValue.children.length; j++){if(oldValue.children[j].sel == ch.sel && oldValue.children[j].key == ch.key){isExist = true;	}}if(!isExist){console.log(ch, i);let dom = createElement(ch);ch.elm = dom;}}else{// 3.2.2.3、老节点没有chidlren// 3.2.2.4、清空老节点内容oldValue.elm.innerHTML = '';// 3.2.2.5、遍历新的vnode子节点,创建DOM,上树for(let i = 0; i < newVnode.children.length; i++){let dom = createElement(newVnode.children[i]);oldVnode.elm.appendChild(dom);}}}}else{	console.log('不是同一个节点')let newVnoElm = createElement(newVnode);// 4、插入到老节点之前oldValue.elm.parentNode.insertBefore(newVnodeElm, oldVnode.elm);}
}

4、diff 算法原理

  • 只对比父节点相同的新旧子节点(Vnode),时间复杂度O(n)
  • 在比较过程中,循环从两边向中间合拢。

​ 4.1、diff是发生在虚拟DOM上的,用来计算两个虚拟DOM的差异,并重新熏染。

// 创建patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule]);// 创建虚拟节点
const myVirtual2 = h('ul',{},[h('li',{key:'A'},'A'),h('li',{key:'B'},'B'),h('li',{key:'C'},'C'),h('li',{key:'D'},'D'),
]);
// 上树
patch(container, myVirtual2);// 创建替换节点
const myVirtual3 = h('ul',{},[h('li',{key:'D'},'D'),h('li',{key:'A'},'A'),h('li',{key:'B'},'B),h('li',{key:'C'},'C'),h('li',{key:'D'},'D'),
]);

4.3、diff算法新旧节点对比的过程?

img

①先借助key值找到不需要移动的相同节点。 ②再找到相同的节点,进行移动。 ③找不到的,才会新建删除节点,保底处理。

DIFF算法的原理

在新老虚拟DOM对比时:

  • 首先,对比节点本身,判断是否为同一节点,如果不为相同节点,则删除该节点重新创建节点进行替换
  • 如果为相同节点,进行patchVnode,判断如何对该节点的子节点进行处理,先判断一方有子节点,一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
  • 比较如果都有子节点,则进行updateChildren,判断如何对这些新老节点的子节点进行操作(diff核心)。
  • 匹配时,找到相同的子节点,递归比较子节点

4.3、Diff值得注意的地方

  • Diff算法更改前后是同一个DOM节点
  • 选择器、key相同则判断为同一个节点。
  • 只进行同层比较,不会跨层比较。

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

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

相关文章

kuberneters可视化界面-kuboard

一、kuboard安装 可以选用&#xff0c;docker和docker-commpose kuberneters 安装 kuboard官网 1、 docker安装 sudo docker run -d \--restartunless-stopped \--namekuboard \-p 80:80/tcp \-p 10081:10081/tcp \-e KUBOARD_ENDPOINT"http://192.168.1.10:80" …

linux的kali安装,换源,更新包

下载kali kali.org进入官网后点第二个 然后点第一个 解压kali 下载后获得.7z压缩包&#xff0c;建议移动到合适自己电脑的位置进行解压&#xff0c;我喜欢放在D盘 启动kali 双击进入解压出的文件夹&#xff0c;将唯一一个.vmx文件用vmware打开&#xff08;没装的自行提前装…

数据结构奇妙旅程之二叉树题型解法总结

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

【深度学习】CodeFormer训练过程,如何训练人脸修复模型CodeFormer

文章目录 BasicSR介绍环境数据阶段 I - VQGAN阶段 II - CodeFormer (w0)阶段 III - CodeFormer (w1) 代码地址&#xff1a;https://github.com/sczhou/CodeFormer/releases/tag/v0.1.0 论文的一些简略介绍&#xff1a; https://qq742971636.blog.csdn.net/article/details/134…

链路追踪-调用链跟踪-Jaeger

文章目录 一、什么是链路跟踪二、OpenCensusOpenCensus 主要特点OpenTracing标准基本概念Span 三、典型服务端产品什么是OpenTracing?opentracing 使用介绍 四、JaegerJaeger 包含的模块Jaeger-client&#xff08;客户端库&#xff09; 五、Jaeger服务容器化部署过程问题整理 …

csdn黑色背景用法

在edge浏览器下&#xff0c;下载油猴脚本管理器 脚本下载 edge扩展 效果图如下&#xff1a;&#xff1a;&#xff1a;

[ACM学习] 进制转换

进制的本质 本质是每一位的数位上的数字乘上这一位的权重 将任意进制转换为十进制 原来还很疑惑为什么从高位开始&#xff0c;原来从高位开始的&#xff0c;可以被滚动地乘很多遍。 将十进制转换为任意进制

适合深夜发朋友圈的心灵鸡汤(整理70句)

1、很多时候&#xff0c;我们赢得了口舌&#xff0c;却失去了感情。 2、失恋到极致的时候&#xff0c;我真的会用后退来保护自己。 3、全身心地去爱&#xff0c;你可能会受到伤害&#xff0c;但这是完整人生的唯一方式。 4、自由不是想干什么就干什么&#xff0c;而是不想干…

Linux中LVM实验

LVM实验&#xff1a; 1、分区 -L是大小的意思-n名称的意思 从vg0&#xff08;卷组&#xff09;分出来 2、格式化LV逻辑卷 LVM扩容 如果icdir空间不够了&#xff0c; 扩展空间lvextend -L 5G /dev/vg0/lv1 /dev/vg0/lv1(pp,vg,lv) 刷新文件系统xfs_growfs /lvdir VG扩容 …

php:规范小数位数,例:10.00展示为10,10.98展示为10.98

代码 <?php$value 10.98; // 原始的双精度类型值if ($value floor($value)) {$formattedValue number_format($value, 0); // 10.00 转换为 10echo $formattedValue;} else {$formattedValue number_format($value, 2); // 10.98 保持为 10.98echo $formattedValue;} …

Sublime Text 3配置 Java 开发环境

《开发工具系列》 《开发语言-Java》 Sublime Text 3配置 Java 开发环境 一、引言二、主要内容1. 初识 Sublime Text 32. 初识 Java3. 接入 Java3.1 JDK 下载3.2 安装和使用 java3.3 环境变量配置 4. 配置 Java 开发环境5. 编写 Java 代码6. 编译和运行 Java 代码7. 乱码问题 三…

服务器无法访问外网怎么办

目前是互联网时代&#xff0c;网络已经成为人们日常生活中不可或缺的一部分。我们通过网络获取信息、进行沟通、甚至进行工作&#xff0c;因此&#xff0c;保持网络的稳定和通畅是非常重要的。然而&#xff0c;有时候我们可能会遇到一些网络无法访问外网的问题&#xff0c;这给…

作者推荐 | 【深入浅出MySQL】「底层原理」探秘缓冲池的核心奥秘,揭示终极洞察

探秘缓冲池的核心奥秘&#xff0c;揭示终极洞察 缓存池BufferPool机制MySQL缓冲池缓冲池缓冲池的问题 缓冲池的原理数据预读程序的局部性原则&#xff08;集中读写原理&#xff09;时间局部性空间局部性 innodb的数据页查询InnoDB的数据页InnoDB缓冲池缓存数据页InnoDB缓存数据…

[DIOR | DIOR-R]旋转目标检测数据集——基于YOLOv8obb,map50已达81.8%

DIOR是一个用于光学遥感图像目标检测的大规模基准数据集。涵盖20个对象类。这20个对象类是飞机、机场、棒球场、篮球场、桥梁、烟囱、水坝、高速公路服务区、高速公路收费站、港口、高尔夫球场、地面田径场、天桥、船舶、体育场、储罐、网球场、火车站、车辆和风磨。 1. DIOR简…

常见の算法链表问题

时间复杂度 1.链表逆序 package class04;import java.util.ArrayList; import java.util.List;public class Code01_ReverseList {public static class Node {public int value;public Node next;public Node(int data) {value data;}}public static class DoubleNode {publi…

Java 字符串 05 练习-遍历字符串和统计字符个数

代码&#xff1a; import java.util.Scanner; public class practice{public static void main(String[] args) {//键盘录入一个字符串&#xff0c;并进行遍历&#xff1b;Scanner input new Scanner(System.in);System.out.println("输入一个字符串&#xff1a;")…

webassembly003 whisper.cpp的main项目-1

参数设置 /home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug/bin/main options:-h, --help [default] show this help message and exit-t N, --threads N [4 ] number of threads to use during computation-p N, --processors …

Android App开发-简单控件(2)——视图基础

2.2 视图基础 本节介绍视图的几种基本概念及其用法&#xff0c;包括如何设置视图的宽度和高度&#xff0c;如何设置视图的外部间距和内部间距&#xff0c;如何设置视图的外部对齐方式和内部对齐方式等等。 2.2.1 设置视图的宽高 手机屏幕是块长方形区域&#xff0c;较短的那…

【星海随笔】unix 启动问题记录.

启动Ubuntu操作系统时&#xff0c;直接进入GRUB状态。 调试时候&#xff0c;曾显示 no bootable device no known filesystem detected 注意&#xff1a; 目前 GRUB 分成 GRUB legacy 和 GRUB 2。版本号是 0.9x 以及之前的版本都称为 GRUB Legacy &#xff0c;从 1.x 开始的就称…

NODE笔记 2 使用node操作飞书多维表格

前面简单介绍了node与简单的应用&#xff0c;本文通过结合飞书官方文档 使用node对飞书多维表格进行简单的操作&#xff08;获取token 查询多维表格recordid&#xff0c;删除多行数据&#xff0c;新增数据&#xff09; 文章目录 前言 前两篇文章对node做了简单的介绍&#xff…