360浏览器怎么加入可信站点/全球搜索引擎市场份额
目录
1. 前言
2. patch
3. 创建节点
4. 删除节点
5. 更新节点
6. 总结
1. 前言
在上一篇文章介绍VNode
的时候我们说了,VNode
最大的用途就是在数据变化前后生成真实DOM
对应的虚拟DOM
节点,然后就可以对比新旧两份VNode
,找出差异所在,然后更新有差异的DOM
节点,最终达到以最少操作真实DOM
更新视图的目的。而对比新旧两份VNode
并找出差异的过程就是所谓的DOM-Diff
过程。DOM-Diff
算法是整个虚拟DOM
的核心所在,那么接下来,我们就以源码出发,深入研究一下Vue
中的DOM-Diff
过程是怎样的。
2. patch
在Vue
中,把 DOM-Diff
过程叫做patch
过程。patch,意为“补丁”,即指对旧的VNode
修补,打补丁从而得到新的VNode
,非常形象哈。那不管叫什么,其本质都是把对比新旧两份VNode
的过程。我们在下面研究patch
过程的时候,一定把握住这样一个思想:所谓旧的VNode
(即oldVNode
)就是数据变化之前视图所对应的虚拟DOM
节点,而新的VNode
是数据变化之后将要渲染的新的视图所对应的虚拟DOM
节点,所以我们要以生成的新的VNode
为基准,对比旧的oldVNode
,如果新的VNode
上有的节点而旧的oldVNode
上没有,那么就在旧的oldVNode
上加上去;如果新的VNode
上没有的节点而旧的oldVNode
上有,那么就在旧的oldVNode
上去掉;如果某些节点在新的VNode
和旧的oldVNode
上都有,那么就以新的VNode
为准,更新旧的oldVNode
,从而让新旧VNode
相同。
可能你感觉有点绕,没关系,我们在说的通俗一点,你可以这样理解:假设你电脑上现在有一份旧的电子版文档,此时老板又给了你一份新的纸质板文档,并告诉你这两份文档内容大部分都是一样的,让你以新的纸质版文档为准,把纸质版文档做一份新的电子版文档发给老板。对于这个任务此时,你应该有两种解决方案:一种方案是不管它旧的文档内容是什么样的,统统删掉,然后对着新的纸质版文档一个字一个字的敲进去,这种方案就是不用费脑,就是受点累也能解决问题。而另外一种方案是以新的纸质版文档为基准,对比看旧的电子版文档跟新的纸质版文档有什么差异,如果某些部分在新的文档里有而旧的文档里没有,那就在旧的文档里面把这些部分加上;如果某些部分在新的文档里没有而旧的文档里有,那就在旧的文档里把这些部分删掉;如果某些部分在新旧文档里都有,那就对比看有没有需要更新的,最后在旧的文档里更新一下,最终达到把旧的文档变成跟手里纸质版文档一样,完美解决。
对比以上两种方案,显然你和Vue
一样聪明,肯定会选择第二种方案。第二种方案里的旧的电子版文档对应就是已经渲染在视图上的oldVNode
,新的纸质版文档对应的是将要渲染在视图上的新的VNode
。总之一句话:以新的VNode为基准,改造旧的oldVNode使之成为跟新的VNode一样,这就是patch过程要干的事。
说了这么多,听起来感觉好像很复杂的样子,其实不然,我们仔细想想,整个patch
无非就是干三件事:
- 创建节点:新的
VNode
中有而旧的oldVNode
中没有,就在旧的oldVNode
中创建。 - 删除节点:新的
VNode
中没有而旧的oldVNode
中有,就从旧的oldVNode
中删除。 - 更新节点:新的
VNode
和旧的oldVNode
中都有,就以新的VNode
为准,更新旧的oldVNode
。
OK,到这里,你就对Vue
中的patch
过程理解了一半了,接下来,我们就逐个分析,看Vue
对于以上三件事都是怎么做的。
3. 创建节点
在上篇文章中我们分析了,VNode
类可以描述6种类型的节点,而实际上只有3种类型的节点能够被创建并插入到DOM
中,它们分别是:元素节点、文本节点、注释节点。所以Vue
在创建节点的时候会判断在新的VNode
中有而旧的oldVNode
中没有的这个节点是属于哪种类型的节点,从而调用不同的方法创建并插入到DOM
中。
其实判断起来也不难,因为这三种类型的节点其特点非常明显,在源码中是怎么判断的:
// 源码位置: /src/core/vdom/patch.js
function createElm (vnode, parentElm, refElm) {const data = vnode.dataconst children = vnode.childrenconst tag = vnode.tagif (isDef(tag)) {vnode.elm = nodeOps.createElement(tag, vnode) // 创建元素节点createChildren(vnode, children, insertedVnodeQueue) // 创建元素节点的子节点insert(parentElm, vnode.elm, refElm) // 插入到DOM中} else if (isTrue(vnode.isComment)) {vnode.elm = nodeOps.createComment(vnode.text) // 创建注释节点insert(parentElm, vnode.elm, refElm) // 插入到DOM中} else {vnode.elm = nodeOps.createTextNode(vnode.text) // 创建文本节点insert(parentElm, vnode.elm, refElm) // 插入到DOM中}}
从上面代码中,我们可以看出:
- 判断是否为元素节点只需判断该
VNode
节点是否有tag
标签即可。如果有tag
属性即认为是元素节点,则调用createElement
方法创建元素节点,通常元素节点还会有子节点,那就递归遍历创建所有子节点,将所有子节点创建好之后insert
插入到当前元素节点里面,最后把当前元素节点插入到DOM
中。 - 判断是否为注释节点,只需判断
VNode
的isComment
属性是否为true
即可,若为true
则为注释节点,则调用createComment
方法创建注释节点,再插入到DOM
中。 - 如果既不是元素节点,也不是注释节点,那就认为是文本节点,则调用
createTextNode
方法创建文本节点,再插入到DOM
中。
代码中的
nodeOps
是Vue
为了跨平台兼容性,对所有节点操作进行了封装,例如nodeOps.createTextNode()
在浏览器端等同于document.createTextNode()
以上就完成了创建节点的操作,其完整流程图如下:
4. 删除节点
如果某些节点再新的VNode
中没有而在旧的oldVNode
中有,那么就需要把这些节点从旧的oldVNode
中删除。删除节点非常简单,只需在要删除节点的父元素上调用removeChild
方法即可。源码如下:
function removeNode (el) {const parent = nodeOps.parentNode(el) // 获取父节点if (isDef(parent)) {nodeOps.removeChild(parent, el) // 调用父节点的removeChild方法}}
5. 更新节点
创建节点和删除节点都比较简单,而更新节点就相对较为复杂一点了,其实也不算多复杂,只要理清逻辑就能理解了。
更新节点就是当某些节点在新的VNode
和旧的oldVNode
中都有时,我们就需要细致比较一下,找出不一样的地方进行更新。
介绍更新节点之前,我们先介绍一个小的概念,就是什么是静态节点?我们看个例子:
<p>我是不会变化的文字</p>
上面这个节点里面只包含了纯文字,没有任何可变的变量,这也就是说,不管数据再怎么变化,只要这个节点第一次渲染了,那么它以后就永远不会发生变化,这是因为它不包含任何变量,所以数据发生任何变化都与它无关。我们把这种节点称之为静态节点。
OK,有了这个概念以后,我们开始更新节点。更新节点的时候我们需要对以下3种情况进行判断并分别处理:
-
如果
VNode
和oldVNode
均为静态节点我们说了,静态节点无论数据发生任何变化都与它无关,所以都为静态节点的话则直接跳过,无需处理。
-
如果
VNode
是文本节点如果
VNode
是文本节点即表示这个节点内只包含纯文本,那么只需看oldVNode
是否也是文本节点,如果是,那就比较两个文本是否不同,如果不同则把oldVNode
里的文本改成跟VNode
的文本一样。如果oldVNode
不是文本节点,那么不论它是什么,直接调用setTextNode
方法把它改成文本节点,并且文本内容跟VNode
相同。 -
如果
VNode
是元素节点如果
VNode
是元素节点,则又细分以下两种情况:-
该节点包含子节点
如果新的节点内包含了子节点,那么此时要看旧的节点是否包含子节点,如果旧的节点里也包含了子节点,那就需要递归对比更新子节点;如果旧的节点里不包含子节点,那么这个旧节点有可能是空节点或者是文本节点,如果旧的节点是空节点就把新的节点里的子节点创建一份然后插入到旧的节点里面,如果旧的节点是文本节点,则把文本清空,然后把新的节点里的子节点创建一份然后插入到旧的节点里面。
-
该节点不包含子节点
如果该节点不包含子节点,同时它又不是文本节点,那就说明该节点是个空节点,那就好办了,不管旧节点之前里面都有啥,直接清空即可。
-
OK,处理完以上3种情况,更新节点就算基本完成了,接下来我们看下源码中具体是怎么实现的,源码如下:
// 更新节点
function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {// vnode与oldVnode是否完全一样?若是,退出程序if (oldVnode === vnode) {return}const elm = vnode.elm = oldVnode.elm// vnode与oldVnode是否都是静态节点?若是,退出程序if (isTrue(vnode.isStatic) &&isTrue(oldVnode.isStatic) &&vnode.key === oldVnode.key &&(isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {return}const oldCh = oldVnode.childrenconst ch = vnode.children// vnode有text属性?若没有:if (isUndef(vnode.text)) {// vnode的子节点与oldVnode的子节点是否都存在?if (isDef(oldCh) && isDef(ch)) {// 若都存在,判断子节点是否相同,不同则更新子节点if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)}// 若只有vnode的子节点存在else if (isDef(ch)) {/*** 判断oldVnode是否有文本?* 若没有,则把vnode的子节点添加到真实DOM中* 若有,则清空Dom中的文本,再把vnode的子节点添加到真实DOM中*/if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)}// 若只有oldnode的子节点存在else if (isDef(oldCh)) {// 清空DOM中的子节点removeVnodes(elm, oldCh, 0, oldCh.length - 1)}// 若vnode和oldnode都没有子节点,但是oldnode中有文本else if (isDef(oldVnode.text)) {// 清空oldnode文本nodeOps.setTextContent(elm, '')}// 上面两个判断一句话概括就是,如果vnode中既没有text,也没有子节点,那么对应的oldnode中有什么就清空什么}// 若有,vnode的text属性与oldVnode的text属性是否相同?else if (oldVnode.text !== vnode.text) {// 若不相同:则用vnode的text替换真实DOM的文本nodeOps.setTextContent(elm, vnode.text)}
}
上面代码里注释已经写得很清晰了,接下来我们画流程图来梳理一下整个过程,流程图如下:
通过对照着流程图以及代码,相信更新节点这部分逻辑你很容易就能理解了。
另外,你可能注意到了,如果新旧VNode
里都包含了子节点,那么对于子节点的更新在代码里调用了updateChildren
方法,而这个方法的逻辑到底是怎样的我们放在下一篇文章中展开学习。
6. 总结
在本篇文章中我们介绍了Vue
中的DOM-Diff
算法:patch过程。我们先介绍了算法的整个思想流程,然后通过梳理算法思想,了解了整个patch
过程干了三件事,分别是:创建节点,删除节点,更新节点。并且对每件事情都对照源码展开了细致的学习,画出了其逻辑流程图。另外对于更新节点中,如果新旧VNode
里都包含了子节点,我们就需要细致的去更新子节点,关于更新子节点的过程我们在下一篇文章中展开学习。
相关文章:

Vue源码系列讲解——虚拟DOM篇【二】(Vue中的DOM-Diff)
目录 1. 前言 2. patch 3. 创建节点 4. 删除节点 5. 更新节点 6. 总结 1. 前言 在上一篇文章介绍VNode的时候我们说了,VNode最大的用途就是在数据变化前后生成真实DOM对应的虚拟DOM节点,然后就可以对比新旧两份VNode,找出差异所在&…...

基于AST实现一键自动提取替换国际化文案
背景:在调研 formatjs/cli 使用(使用 formatjs/cli 进行国际化文案自动提取 )过程中,发现有以下需求formatjs/cli 无法满足: id 需要一定的语义化; defaultMessage和Id不能直接hash转换; 需要…...

嵌入式硬件工程师与嵌入式软件工程师
嵌入式硬件工程师与嵌入式软件工程师 纯硬件设备与嵌入式设备 纯硬件设备是指内部不包含微处理器,无需烧写软件就能够运行的电子设备。如天线、老式收音机、老式电视机、老式洗衣机等。这类设备通常功能简单,易于操作,用户通常只需要打开电…...

【华为云】云上两地三中心实践实操
写在前面 应用上云之后,如何进行数据可靠性以及业务连续性的保障是非常关键的,通过华为云云上两地三中心方案了解相关方案认证地址:https://connect.huaweicloud.com/courses/learn/course-v1:HuaweiXCBUCNXI057Self-paced/about当前内容为华…...

Linux大集合
Linux Linux是什么? Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、 支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和 64位硬件。 Linux内核 是一个Linux系统…...

深入解析 Spring 事务机制
当构建复杂的企业级应用程序时,数据一致性和可靠性是至关重要的。Spring 框架提供了强大而灵活的事务管理机制,成为开发者处理事务的首选工具。本文将深入探讨 Spring 事务的使用和原理,为大家提供全面的了解和实际应用的指导。 本文概览 首…...

第9章 安全漏洞、威胁和对策(9.11-9.16)
9.11 专用设备 专用设备王国疆域辽阔,而且仍在不断扩张。 专用设备是指为某一特定目的而设计,供某一特定类型机构使用或执行某一特定功能的任何设备。 它们可被看作DCS、物联网、智能设备、端点设备或边缘计算系统的一个类型。 医疗设备、智能汽车、…...

Mysql-数据库压力测试
安装软件 官方软件 安装插件提供了更多的监听器选项 数据库驱动 数据库测试 配置 这里以一个简单的案例进行,进行连接池为10,20,30的梯度压测: select * from tb_order_item where id 1410932957404114945;新建一个线程组 新增一个连接池配置 新建一…...

CI/CD总结
bitbucket deployment: Bitbucket Cloud resources | Bitbucket Cloud | Atlassian Support Jenkins:...

【CSS】margin塌陷和margin合并及其解决方案
【CSS】margin塌陷和margin合并及其解决方案 一、解决margin塌陷的问题二、避免外边距margin重叠(margin合并) 一、解决margin塌陷的问题 问题:当父元素包裹着一个子元素且父元素没有边框的时候,当给子元素设置margin-top:100px&…...

Python并发
Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多线程(Thread)的情况下,不能发挥多核的优势。而使用多进程(Multiprocess),则可以发挥多核的优势真正地提高效率。…...

2024-02-04(hive)
1.Hive中的分区表 可以选择字段作为表分区。 分区其实就是HDFS上的不同文件夹。 分区表可以极大的提高特定场景下Hive的操作性能。 2.分区语法 create table tablename(...) partitioned by (分区列 列类型, ...) row format delimited fields terminated by ; 3.Hive中的…...

P9420 [蓝桥杯 2023 国 B] 子 2023 / 双子数--2024冲刺蓝桥杯省一
点击跳转例题 子2023思路:dp。最开始想着枚举,但是超时,想着优化以下,但是还是不行。 那么切换算法,应该是dp: 1.f [i] 表示当前字符串 以 2023 为第 i 位的数量方案:如f [0] 表示 前i个字符串…...

The Back-And-Forth Method (BFM) for Wasserstein Gradient Flows windows安装
本文记录了BFM算法代码在windows上的安装过程。 算法原网站:https://wasserstein-gradient-flows.netlify.app/ github:https://github.com/wonjunee/wgfBFMcodes 文章目录 FFTWwgfBFMcodesMATLABpython注 FFTW 官网/下载路径:https://ww…...

【GAMES101】Lecture 19 透镜
目录 理想的薄透镜 模糊 利用透镜模型做光线追踪 景深(Depth of Field) 理想的薄透镜 在实际的相机中都是用的一组透镜来作为这个镜头 这个因为真实的棱镜无法将光线真正聚焦到一个点上,它只能聚在一堆上 所以方便研究提出了一种理想化的…...

防范恶意勒索攻击!亚信安全发布《勒索家族和勒索事件监控报告》
本周态势快速感知 本周全球共监测到勒索事件81起,事件数量有所下降,比上月降低20%。 lockbit3.0仍然是影响最严重的勒索家族;akira和incransom也是两个活动频繁的恶意家族,需要注意防范。 本周alphv勒索组织窃取MBC法律专业公司…...

AR人脸106240点位检测解决方案
美摄科技针对企业需求推出了AR人脸106/240点位检测解决方案,为企业提供高效、精准的人脸识别服务,采用先进的人脸识别算法和机器学习技术,通过高精度、高速度的检测设备,对人脸进行快速、准确地定位和识别。该方案适用于各种应用场…...

数字图像处理实验记录八(图像压缩实验)
前言:做这个实验的时候很忙,就都是你抄我我抄你了 一、基础知识 1.为什么要进行图像压缩: 图像的数据量巨大,对计算机的处理速度、存储容量要求高。传输信道带宽、通信链路容量一定,需要减少传输数据量&a…...

navigator.mediaDevices.getUserMedia获取本地音频/麦克权限并提示用户
navigator.mediaDevices.getUserMedia获取本地音频/麦克权限并提示用户 效果获取权限NotFoundErrorNotAllowedError 代码 效果 获取权限 NotFoundError NotAllowedError 代码 // 调用 captureLocalMedia()// 方法 function captureLocalMedia() {console.warn(Requesting lo…...

CTF-show WEB入门--web19
今晚web19也就顺便解决了 老样子我们先打开题目看看题目提示: 可以看到题目提示为: 密钥什么的,就不要放在前端了 然后我们打开题目链接: 然后我们查看网页源代码: 可以发现有用的内容全在网页源代码里。 前端验证…...

04 使用gRPC实现客户端和服务端通信
使用gRPC实现客户端和服务端通信 参考文档: 基于C#的GRPC 1 创建项目和文件夹 GrpcClientDemoGrpcServerDemoProtos解决方案和文件夹1.1 添加nuget依赖 客户端和服务器都要有依赖和gRPC_Objects文件夹 <ItemGroup><PackageReference Include"Google.Protobu…...

设计模式-行为型模式(下)
1.访问者模式 访问者模式在实际开发中使用的非常少,因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差,可维护性变差,在没有特别必要的情况下,不建议使用访问者模式. 访问者模式(Visitor Pattern) 的原始定义是: 允许在运行时将一个或多个操作应用于一…...

华为交换机常用命令
一、查看命令 1、查看交换机信息 display version 查看交换机软件版本display clock 查看交换机时钟2、查看交换机配置 display saved-configuration 显示系统保存配置display current-configuration 显示系统当前配置 3、查看当前对象信息 display this …...

【Linux】信号-上
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:题目解析 🌎推荐文章:【LeetCode】winter vacation training 目录 👉🏻信号的概念与产生jobs命令普通信号和实…...

uniapp 开发App 权限授权 js-sdk
从官网的插件市场下载的: 直接上代码: /*** 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启*/var isIos // #ifdef APP-PLUS isIos (plus.os.name "iOS") // #endif// 判断推送权限是否开启 fu…...

【01】判断素数/质数(C语言)
目录 (1)素数特点:只能被1和本身整除 (2)代码如下: (3)运行结果如下 编辑 (4)函数引申 (1)素数特点:只能被1和本身…...

特征工程:特征提取和降维-上
目录 一、前言 二、正文 Ⅰ.主成分分析 Ⅱ.核主成分分析 三、结语 一、前言 前面介绍的特征选择方法获得的特征,是从原始数据中抽取出来的,并没有对数据进行变换。而特征提取和降维,则是对原始数据的特征进行相应的数据变换,并…...

前端JavaScript篇之强类型语言和弱类型语言的区别和对比
目录 强类型语言和弱类型语言的区别和对比总结 强类型语言和弱类型语言的区别和对比 强类型语言和弱类型语言是编程语言的两种不同类型系统,它们处理变量类型的方式有所不同。 强类型语言: 强类型语言要求在使用变量之前必须明确声明其类型,…...

[红日靶机渗透] ATKCK红队评估实战靶场三
🍬 博主介绍👨🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【ATK&CK红队评估实战靶场】 【VulnHub靶场复现】【面试分析】 …...

网课:N皇后问题——牛客(题解和疑问)
题目描述 给出一个nnn\times nnn的国际象棋棋盘,你需要在棋盘中摆放nnn个皇后,使得任意两个皇后之间不能互相攻击。具体来说,不能存在两个皇后位于同一行、同一列,或者同一对角线。请问共有多少种摆放方式满足条件。 输入描述: …...