虚拟 DOM 详解

news/2024/4/26 6:19:18/文章来源:https://blog.csdn.net/TongJ_/article/details/129128056

什么是虚拟 dom?

虚拟 dom 本质上就是一个普通的 JS 对象,用于描述视图的界面结构 在vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟 dom 树,这也就意味着每个组件都对应一棵虚拟 DOM 树

查看虚拟 DOM:

mounted() {console.log(this._vnode);
},// vdom 结构:javascript
var vnode = {tag: "h1",children: [{ tag: undefined, text: "第一个vue应用:Hello World" }],
};

上面的对象描述了:有一个标签名为 h1 的节点,它有一个子节点,该子节点是一个文本,内容为第一个 vue 应用:Hello World

为什么需要虚拟 dom

vue中,渲染视图会调用render函数,这种渲染不仅发生在组件创建时,同时发生在视图依赖的数据更新时。如果在渲染时,直接使用真实DOM,由于真实DOM的创建、更新、插入等操作会带来大量的性能损耗,从而就会极大的降低渲染效率。 因此,vue在渲染时,使用虚拟 dom 来替代真实 dom,主要为解决渲染效率的问题。

对比 JS 对象和真实 DOM 对象

var times = 10000000;
console.time(`js object`);
for (var i = 0; i < times; i++) {var obj = {};
}
console.timeEnd("js object");
console.time(`dom object`);
for (var i = 0; i < times; i++) {var obj = document.createElement("div");
}
console.timeEnd("dom object");

虚拟 dom 是如何转换为真实 dom 的?
在一个组件实例首次被渲染时,它先生成虚拟 dom 树,然后根据虚拟 dom 树创建真实 dom,并把真实 dom 挂载到页面中合适的位置,此时,每个虚拟 dom 便会对应一个真实的 dom这时候虚拟 dom 多一个创建虚拟 dom 树的过程,所以效率比真实 dom 低。

如果一个组件受响应式数据变化的影响,需要重新渲染时,它仍然会重新调用 render 函数,创建出一个新的虚拟 dom 树,用新树和旧树对比,通过对比,vue 会找到最小更新量,然后更新必要的虚拟 dom 节点,最后,这些更新过的虚拟节点,会去修改它们对应的真实 dom

实际直接使用新树,抛弃旧树,只更新必要的真实 dom 这样一来,就保证了对真实 dom 达到最小的改动

虚拟 DOM 树会最终生成为真实的 DOM 树,这个过程叫渲染 当数据变化后,将引发重新渲染,vue 会比较新旧两棵 vnode tree,找出差异,然后仅把差异部分应用到真实 dom tree 中。对比的是对象,效率很高

可见,在 vue 中,要得到最终的界面,必须要生成一个 vnode tree

渲染的本质:render 生成虚拟 DOM

模板和虚拟 dom 的关系

vue 框架中有一个compile模块,它主要负责将模板(实际上是字符串)转换为render函数,而render函数调用后将得到虚拟 dom。

编译的过程分两步:

  • 将模板字符串转换成为AST抽象语法树

  • 将AST转换为render函数

AST 是什么? 一句话概括:使用 js 树形结构描述原始代码

如果使用传统的引入方式(script 的 src),则编译时间发生在组件第一次加载时,这称之为运行时编译。

如果是在vue-cli的默认配置下,编译发生在打包时,这称之为模板预编译。(打包的时候编译完成)

编译是一个极其耗费性能的操作,预编译可以有效的提高运行时的性能,而且,由于运行的时候已不需要编译,vue-cli在打包时会排除掉vue中的compile模块,以减少打包体积

//vue config.js
module.export = {runtimeCompiler: true, //打包的时候要不要包含运行时候编译,默认false,不建议使用true
};

模板的存在,仅仅是为了让开发人员更加方便的书写界面代码

vue 最终运行的时候,最终需要的是 render 函数,而不是模板,因此,模板中的各种语法,在虚拟 dom 中都是不存在的,它们都会变成虚拟 dom 的配置

总之:模板会编译成 render 方法,最终总是 render()

注意:虚拟节点树必须是单根的,所以模板必须单根

模版预编译

vue-cli进行打包时,会直接把组件中的模板转换为render函数,这叫做模板预编译 这样做的好处在于:

运行时就不再需要编译模板了,提高了运行效率
打包结果中不再需要 vue 的编译代码,减少了打包体积

易混淆:vue-cli 打包存在预编译,发现有模板,会覆盖 render;

在 vue 中,如果有模板和 render,则 render 优先

挂载

将生成的真实 DOM 树,放置到某个元素位置,称之为挂载 挂载的方式:

通过el:"css选择器"进行配置
通过vue实例.$mount(“css选择器”)进行配置

总结:完整流程

Vue template 到 render 的过程

vue 的模版编译过程主要如下:template -> ast -> render 函数 vue 在模版编译版本的码中会执行 compileToFunctions 将 template 转化为 render 函数:

// 将模板编译为render函数
const { render, staticRenderFns } = compileToFunctions(template,options//省略}, this)

CompileToFunctions 中的主要逻辑如下 ∶

(1)调用 parse 方法将 template 转化为 ast(抽象语法树)

constast = parse(template.trim(), options);

parse 的目标:把 tamplate 转换为 AST 树,它是一种用 JavaScript 对象的形式来描述整个模板。

解析过程:利用正则表达式顺序解析模板,当解析到开始标签、闭合标签、文本的时候都会分别执行对应的 回调函数,来达到构造 AST 树的目的。

AST 元素节点总共三种类型:type 为 1 表示普通元素、2 为表达式、3 为纯文本

(2)对静态节点做优化

optimize(ast, options);

这个过程主要分析出哪些是静态节点,给其打一个标记,为后续更新渲染可以直接跳过静态节点做优化

深度遍历 AST,查看每个子树的节点元素是否为静态节点或者静态节点根。如果为静态节点,他们生成的 DOM 永远不会改变,这对运行时模板更新起到了极大的优化作用。

(3)生成代码

const code = generate(ast, options);

generate 将 ast 抽象语法树编译成 render 字符串并将静态部分放到 staticRenderFns 中,最后通过 new Function(render) 生成 render 函数。

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

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

相关文章

C#中多态、抽象类、虚方法

多态、重装、重写 •多态&#xff1a;同一操作作用于不同的对象&#xff0c;可以有不同的解释&#xff0c;产生不同的执行结果&#xff0c;这就是多态性。抽象类、虚函数、接口三种方法实现的可以是多态性。•重载&#xff08;overload&#xff09;&#xff1a;对象中同名函数&…

JSP 质量管理系统myeclipse定制开发sqlserver数据库网页模式java编程jdbc

一、源码特点 JSP 质量管理系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开 发&#xff0c;数据库为SQLServer2008&#xff0c…

二、最基本的vuex的使用

二、最基本的vuex的使用&#xff1a; 学习任何技术&#xff0c;先找到没有用这个技术时&#xff0c;给我们带来了什么麻烦 而这个新技术是怎么帮我们解决这些问题的。 理解方式&#xff1a; state&#xff1a;装数据的一个对象 mutations&#xff1a;装方法的一个对象&#…

hydra常见端口服务穷举

目录 工具介绍 参数说明 官方示例 官方字典 ssh爆破 ftp爆破 mysql爆破 smb爆破 rdb爆破 http爆破 redis爆破 工具介绍 hydra 是一个支持众多协议的爆破工具&#xff0c;已经集成到KaliLinux中&#xff0c;直接在终端打开即可 参数说明 -l &#xff1a; 指定破…

mybatis狂神(附自学过程中疑问解决)

首先先附上mybatis的官方文本链接mybatis – MyBatis 3 | 简介一、Mybatis介绍MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来…

RK3288 GPIO记录

1、引脚对应的GPIO 编号第一种 使用/sys/kernel/debug/gpio查询所有gpio引脚的基数第二种 cat /sys/class/gpio/gpiochip248/label对应的label就是GPIO引脚&#xff0c;例如下图GPIO8对应的基数就是2482、计算编号编号 基数 PIN脚如GPIO8的基数是248&#xff0c; GPIO8_A6的编…

django项目实战三(django+bootstrap实现增删改查)进阶分页

目录 一、分页 1、修改case_list.html页面 2、修改views.py的case_list方法&#xff08;分页未封装&#xff09; 二、分页封装 1、新建类Pagination 2、修改views.py的case_list方法 三、再优化&#xff0c;实现搜索分页qing情况 四、优化其他查询页面实现分页和查询 五…

MySQL —— 内外连接

目录 表的内外连接 一、内连接 二、外连接 1. 左外连接 2. 右外连接 表的内外连接 表的连接分为内连和外连 一、内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;我们前面博客中的查询都是内连接&#xff0c;也是在开发过程中使用的最多…

Java面试题--熔断和降级的区别

熔断和降级都是系统自我保护的一种机制&#xff0c;但二者又有所不同&#xff0c;它们的区别主要体现在以下几点&#xff1a; 概念不同 触发条件不同 归属关系不同 1.概念不同 1.1熔断概念 “熔断”一词早期来自股票市场。熔断&#xff08;Circuit Breaker&#xff09;也…

JavaWab开发的总括以及HTML知识

一、Web开发的总括在这里我来给大家介绍一下Wab开发需要配合哪些前后端的对应语言:首先是Java(Java通常的工作):Wab开发android开发大数据开发另外,Wab开发想要学好就需要配合之前博客中的内容,如:多线程/IO/网络/数据结构/数据库......这里建议学懂前面的内容再往下走.JavaWab…

Python采集双色球数据,做数据分析,让我自己实现自己的富豪梦

来唠点嗑&#xff1f; 咳咳&#xff0c;最近是咋的了&#xff0c;某站掀起了一股双色球热潮&#xff1f;一般我自己的账号上&#xff0c;是很少看到关于python这些内容的&#xff0c;都是小姐姐和热梗&#xff0c;或者其他搞笑视频 由于&#x1f4b4;的吸引力…手不自觉的就点…

2023年TS4 入门笔记【慕课网imooc】【Vue3+React18 + TS4考勤系统】

目录 安装ts 基础 类型声明和变量声明 类型注解和类型判断 类型分类与联合类型与交叉类型​编辑 never类型与any类型与unknown类型 类型断言与非空断言 数组类型和元祖类型 对象类型与索引签名 函数类型与void类型 函数重载与可调用注解 枚举类型与const枚举 进阶…

2023年美国大学生数学建模A题:受干旱影响的植物群落建模详解+模型代码(二)

前言 资源放CSDN上面过不了审核,都快结束了都没过审真的麻了,订阅专栏的同学直接加我微信直接发你。我只打造优质专栏。专注建模四年,博主参与过大大小小数十来次数学建模,理解各类模型原理以及每种模型的建模流程和各类题目分析方法。此专栏的目的就是为了让零基础快速使…

【2023-02-20】JS逆向之翼支付

提示&#xff1a;文章仅供参考&#xff0c;禁止用于非法途径 文章目录前言分析总结前言 真的好久没更了…… 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 分析 进到网页&#xff0c;加载两个接口 applyLoginFactor 接口返回一个RSA公钥&#xff0…

工业4.0和工业物联网如何协同工作

虽然许多公司已经接受了工业物联网&#xff0c;但他们现在必须接受工业4.0对数据驱动的数字化转型的承诺。随着制造业、能源、公用事业和供应链应用迅速采用工业物联网(IIoT)&#xff0c;这些行业的新现实正在形成。工业物联网提供了企业管理数千个活动部件所需的数据类型&…

【部署】项目正式服部署更新

chihiro-notes 千寻简笔记 v0.1 内测版 &#x1f4d4; 笔记介绍 大家好&#xff0c;千寻简笔记是一套全部开源的企业开发问题记录&#xff0c;毫无保留给个人及企业免费使用&#xff0c;我是作者星辰&#xff0c;笔记内容整理并发布&#xff0c;内容有误请指出&#xff0c;笔…

第一章 初识 Spring Security

第一章 初识 Spring Security 1、权限管理 权限管理 基本上涉及到用户参与的系统都要进行权限管理&#xff0c;权限管理属于系统安全的范畴&#xff0c;权限管理实现了对用户访问系统的控制&#xff0c;按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资…

计算机网络学习笔记02

学习视频&#xff1a;https://www.bilibili.com/video/BV1c4411d7jb/?p7&spm_id_frompageDriver&vd_source75dce036dc8244310435eaf03de4e330 一、计算机网络体系结构 1 常见的计算机网络体系结构 OSI体系结构和TCP/IP体系结构 TCP/IP体系结构的网络接口层并没有规…

鼠标指针文件格式解析

鼠标指针文件格式解析 文章目录鼠标指针文件格式解析windowsico文件格式分析文件头&#xff1a;图像数据头段&#xff1a;图像数据段&#xff1a;Ani动态光标格式解析数据结构&#xff1a;anihseq **rate**LISTcur静态光标文件格式解析macOSLinuxwindows ico文件格式分析 是一…

【Java基础】IO流

IO流 最后一定要关闭流&#xff0c;防止资源泄露 字节流 一次读取1字节&#xff0c;8比特 FileInputStream import org.junit.jupiter.api.Test;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;public class CopyBytes {pub…