vue源码解析patch.js

前言:在vue2.0 中,VNode转换成真正的DOM是通过patch(oldVNode,VNode,hydrating)方法实现的。
源码目录:/vue/src/core/vdom/patch.ts

  // oldVnode 一个真实的DOM或者一个Vnode对象// vnode 一个待替换的Vnode对象// hydrating 是否支持服务端渲染// removeOnly function patch(oldVnode, vnode, hydrating, removeOnly) {if (isUndef(vnode)) { // 如果没有新的Vnode节点//执行destroy钩子函数if (isDef(oldVnode)) invokeDestroyHook(oldVnode)return}// isInitialPatch 是 Vue 实例的一个内部属性,用于标记组件是否进行了首次补丁(patch)let isInitialPatch = false // 创建子组件节点,组件vnode会被铺设到这个队列中const insertedVnodeQueue: any[] = []if (isUndef(oldVnode)) {// empty mount (likely as component), create new root element// 空挂载(可能作为组件),创建新的根元素isInitialPatch = true// 创建组件节点元素// createElm 创建新节点,初始化创建函数。createElm(vnode, insertedVnodeQueue)} else {const isRealElement = isDef(oldVnode.nodeType)// 如果不是真实的dom,且新旧vnode 同级比较一致if (!isRealElement && sameVnode(oldVnode, vnode)) {// patch existing root node// patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly):负责找出差异,diff算法,DOM的更新。patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly)} else {// 如果是真实的DOM节点。if (isRealElement) {// mounting to a real element// check if this is server-rendered content and if we can perform// a successful hydration.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} else if (__DEV__) {warn('The client-side rendered virtual DOM tree is not matching ' +'server-rendered content. This is likely caused by incorrect ' +'HTML markup, for example nesting block-level elements inside ' +'<p>, or missing <tbody>. Bailing hydration and performing ' +'full client-side render.')}}// 不是服务端渲染,或者 hydration 失败,则根据 oldVnode 创建一个 vnode 节点// either not server-rendered, or hydration failed.// create an empty node and replace itoldVnode = emptyNodeAt(oldVnode)}// replacing existing element// 获取老节点真实domconst oldElm = oldVnode.elm// 获取老节点父级domconst parentElm = nodeOps.parentNode(oldElm)// create new node// 基于新 vnode 创建整棵 DOM 树并插入到 body 元素下createElm(vnode,insertedVnodeQueue,// extremely rare edge case: do not insert if old element is in a// leaving transition. Only happens when combining transition +// keep-alive + HOCs. (#4590)oldElm._leaveCb ? null : parentElm,nodeOps.nextSibling(oldElm))// update parent placeholder node element, recursively// 递归更新父占位符节点元素(异步组件)if (isDef(vnode.parent)) {let ancestor = vnode.parentconst patchable = isPatchable(vnode)while (ancestor) {for (let i = 0; i < cbs.destroy.length; ++i) {cbs.destroy[i](ancestor)}ancestor.elm = vnode.elmif (patchable) {for (let i = 0; i < cbs.create.length; ++i) {cbs.create[i](emptyNode, ancestor)}// #6513// invoke insert hooks that may have been merged by create hooks.// e.g. for directives that uses the "inserted" hook.const insert = ancestor.data.hook.insertif (insert.merged) {// start at index 1 to avoid re-invoking component mounted hookfor (let i = 1; i < insert.fns.length; i++) {insert.fns[i]()}}} else {registerRef(ancestor)}ancestor = ancestor.parent}}// 移除旧节点// destroy old nodeif (isDef(parentElm)) {removeVnodes([oldVnode], 0, 0)} else if (isDef(oldVnode.tag)) {invokeDestroyHook(oldVnode)}}}// 调用insertedVnodeQueue队列中所有子组件的insert钩子invokeInsertHook(vnode, , isInitialPatch)return vnode.elm}

源码逻辑分析

  1. 新节点不存在,旧节点存在,dom移除。
  2. 新节点存在,旧节点不存在,dom新增。
  3. 新旧节点都存在,旧节点不是真实的元素且新旧节点是同一节点,修改(更新)Diff算法。
  4. 新旧节点都存在,旧节点是真实的元素,一般是初始化渲染,旧节点的真实 DOM 也就是传入进来的 vm.$el 对应的元素,比如
    ;这里还有一个情况就是当 vnode.parent 存在,又不是同一节点,进行替换(更新,比如异步组件。

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

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

相关文章

镜像VS快照详细对比

不同之处 依赖性&#xff1a; 快照通常依赖于原始系统的状态或之前的快照。 而镜像是独立的&#xff0c;包含了所需的全部数据。 目的&#xff1a; 镜像用于创建或恢复整个系统&#xff0c;适用于系统迁移、备份或恢复等场景。 快照用于数据恢复&#xff0c;可以快速回滚到之前…

oracle--存储过程基本框架

1.基本语法 create procedure sp_test is--AS BEGINinsert into emp END; 小例子&#xff1a; create procedure sp_emp_bak is BEGINinsert into emp_bak select * from emp where deptno10;commit; END; --第一步编译&#xff1a;(打开编写的存储过程&#xff0c;点击执行…

路由引入实验

配置思路&#xff1a; 1.IP配置&#xff1a; [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip ad 100.1.1.1 24 [R1-GigabitEthernet0/0/0]int l0 [R1-LoopBack0]ip ad 192.168.0.1 32 [R1-LoopBack0]int l1 [R1-LoopBack1]ip ad 192.168.1.1 32 [R1-LoopBack1]q dis ip int bri…

路由过滤,路由策略小实验

目录 一&#xff0c;实验拓扑&#xff1a; 二&#xff0c;实验要求&#xff1a; 三&#xff0c;实验思路&#xff1a; 四&#xff0c;实验过程&#xff1a; 1&#xff0c;IP配置&#xff1a; 2、R1 和R2 运行 RIPv2&#xff0c;R2&#xff0c;R3 和R4运行 oSPF&#xff0…

【Python爬虫】CSS选择器选择多个属性

1.selenium.webdriver和BeautifulSoup 对于单个元素的属性&#xff0c;为每个属性加中括号[] browser Chorme() browser.find_element(byBy.CSS_SELECTOR, value"ul[idp][classl]") 若有从属关系&#xff0c;如下 <select id"dropdown" name"d…

自动化测试及典型开源的自动化测试工具

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

opencv 存储像素值为浮点数的图像 (.tiff)

在存储32CF1格式的深度图像时&#xff0c;怎么也存储不对 存储成jpg格式的&#xff0c;会乱码。be like 13.6的数据存储之后再读取变成…e-30存储成png格式时&#xff0c;会自动把浮点数转换成整数。13.6的数据读取之后就变成14了直接把深度图片存储成.npy格式python处理很简单…

Helm dryRun参数学习

在Kubernetes和Helm中&#xff0c;dryrun参数是一种测试工具&#xff0c;它允许用户在不实际执行操作的情况下预览将要发生的结果。这个参数通常用于验证和测试配置更改&#xff0c;而不需要实际应用这些更改。 在Kubernetes中&#xff0c;你可以使用--dry-runclient或--dry-ru…

【IO流】字符流和字节流

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 Java的IO流是Java中处理输入和输出的重要机制。IO流按照数据流的方向分为输入流和输出流&#xff0c; 按照处理数据的单位分为字节流和字符流。 1. 字节流&#xff…

linux 如何查看Tomcat进程

查看正在运行的Tomcat进程 ps aux | grep tomcatps -ef | grep tomcat 相关介绍&#xff1a; Tomcat启动、停止 首先进入tomcat 所在bin目录 cd /opt/tomcat/bin (需根据个人tomcat目录进入) 关闭tomcat服务: ./shutdown.sh 或则 sh shutdown.sh   启动tomcat: &…

C++ priority_queue 最大堆、最小堆的实现

在C标准库中&#xff0c;priority_queue 是一个容器适配器&#xff0c;它提供了队列的所有基本操作&#xff0c;包括元素的入队&#xff08;push&#xff09;和出队&#xff08;pop&#xff09;&#xff0c;但是出队操作&#xff08;top 和 pop&#xff09;总是返回&#xff08…

首发!这家消金公司引入国资新股东

来源 | 镭射财经&#xff08;leishecaijing&#xff09; 「镭射财经」了解到&#xff0c;锦程消费金融已引入国资新股东成都天府软件园有限公司&#xff0c;原股东优信、浩泽净水已经退出。 成都天府软件园有限公司是成都高新投资集团旗下全资子公司&#xff0c;实际控制人为…

VBA运行后,为什么excel的三个工作表结果一样?

运行完了excel的三个工作表的结果一样&#xff0c;问题在哪呢&#xff1f; 代码如下&#xff1a; Sub 计算成绩() 计算成绩 Macro i为工作表行号 Dim i, m, total As Integer Dim w1 As Worksheet For m 1 To Worksheets.count Set w1 Worksheets(m) i 2 total 0 …

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试 一、背景介绍1.1 RW007模组简介1.2 Arduino接口简介1.3 RW007软件包简介1.4 RT-Thread env工具简介 二、创建工程2.1 新建工程2.2 添加rw007软件包2.3 打开RW007配置项2.4 启用pin驱动2.5 禁用rw007的ST…

举例详解 TCP/IP 五层(或四层)模型与 OSI七层模型对比 (画图详解 一篇看懂!)

目录 一、为什么要对协议进行分层 1、什么是协议分层 2、协议分层的好处 二、TCP/IP 五层&#xff08;或四层&#xff09;模型 1、概念 应用层 传输层 网络层 数据链路层 物理层 2、举例详解 传输层 网络层 数据链路层 和 物理层 应用层 四、TCP/IP 五层&…

《王者荣耀》游戏攻略:角色排行榜——墨子

作为天蝎座黄金圣斗士&#xff0c;墨子以他的正义感和荣誉感闻名&#xff0c;一直站在正义的一方&#xff0c;忠于女神雅典娜。他的猩红毒针象征着审判和死亡&#xff0c;而他所施加的十五针“安达里士”更是生命终结的预兆。在冥王再次发动战争之际&#xff0c;墨子追随雅典娜…

【第4讲】XTuner 微调 LLM:1.8B、多模态、Agent

目录 1 简介2 基础知识2.1 finetune简介2.2 xtuner简介2.2.1 技术架构2.2.2 快速上手xtuner 2.3 8GB显存玩转LLM&#xff08;intern1.8b&#xff09;2.3.1 flash attention vs deepspeed zero2.3.2 相关版本更新和使用 2.4 多模态LLM2.4.1 多模态LLaVA基本原理简介2.4.2 快速上…

MATLAB初学者入门(11)—— 贪心算法

贪心算法是一种简单直观的算法设计方法&#xff0c;常用于解决需要做出一系列选择以达到最优解的问题。贪心算法的核心思想是每一步都选择当前看起来最好的选项&#xff0c;而不考虑大局。这种方法通常易于实现&#xff0c;但不总是能得到全局最优解。下面&#xff0c;将详细介…

CWDM/DWDM系统应用解决方案

波分复用(WDM)包括粗波分复用(CWDM)和密集波分复用(DWDM)。 它是指在一根光纤上同时传输多个不同波长的信号。 主要目的 WDM就是增加光纤的可用带宽&#xff0c;无需铺设额外的光缆即可进行扩容。 因此&#xff0c;被电信公司广泛采用。 CWDM 和 DWDM 有什么区别&#xff1f; …

充电器进阶,原边恒流,单片机控制小电流(预充电)的方案

前言 很多充电器&#xff0c;为了能控制电流输出&#xff0c;也就是充电时需要有小电流、大电流的情况&#xff0c;都会用副边及单片机进行控制&#xff0c;但因为是副边控制&#xff0c;需要一个比较器、一个二极管、若干电阻、若干电容&#xff0c;整体BOM成本可能多了三毛钱…