当前位置: 首页 > news >正文

虚拟 DOM 详解

什么是虚拟 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 函数。

相关文章:

虚拟 DOM 详解

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

Delphi Http Https 最好的解决方法(一)

当前文章主要解决Delphi调用http、https的常见报错。 开发工具: Delphi XE 10.1 Berlin版本 可能所需的控件包&#xff1a; QDAC 请自行下载。 1. 接口描述 dll_init 接口初始化&#xff0c;程序启动时调用&#xff0c;主要是对工具类实例的创建 dll_post 发送post请求&am…...

Allegro无法打开10度走线命令的原因和解决办法

Allegro无法打开10度走线命令的原因和解决办法 做PCB设计的时候,10度走线也是较为常见的设计方式,Allegro支持10度走线,如下图 需要10度走线的时候,Options只需要勾选Route offset命令即可 但有时options处会看不到10度走线的命令,如下图...

Frequency Domain Model Augmentation for Adversarial Attack

原文&#xff1a;[2207.05382] Frequency Domain Model Augmentation for Adversarial Attack (arxiv.org)代码&#xff1a;https://github.com/yuyang-long/SSA.黑盒攻击替代模型与受攻击模型之间的差距通常较大&#xff0c;表现为攻击性能脆弱。基于同时攻击不同模型可以提高…...

react源码中的协调与调度

requestEventTime 其实在React执行过程中&#xff0c;会有数不清的任务要去执行&#xff0c;但是他们会有一个优先级的判定&#xff0c;假如两个事件的优先级一样&#xff0c;那么React是怎么去判定他们两谁先执行呢&#xff1f; // packages/react-reconciler/src/ReactFibe…...

如何快速、全面、深入地掌握一门编程语言

思考路线 如何快速&#xff1f; 什么样的Demo才能让人觉得你掌握了它&#xff1f; 空 判断&#xff1a;构造一个可以判断所有空的 is_empty 函数 for 循环&#xff1a;i 和 集合迭代两种 时间获取&#xff1a;年/月/日 时分秒 时间戳与时间格式互转 休眠时间函数 字符串处理…...

python五子棋代码最简单的,python五子棋代码画棋盘

大家好&#xff0c;本文将围绕python五子棋代码输赢逻辑判断展开说明&#xff0c;如何用python制作五子棋游戏是一个很多人都想弄明白的事情&#xff0c;想搞清楚python五子棋代码最简单的需要先了解以下几个事情。 1、求解用python 编写五子棋怎样编写判断输赢的函数&#xff…...

C++ 智能指针的原理:auto_ptr、unique_ptr、shared_ptr、weak_ptr

目录一、理解智能指针1.普通指针的使用二、智能指针1.auto_ptr2.unique_ptr3.shared_ptr&#xff08;1&#xff09;了解shared_ptr&#xff08;2&#xff09;shared_ptr的缺陷4.weak_ptr本文代码在win10的vs2019中通过编译。 一、理解智能指针 1.普通指针的使用 如果程序需要…...

二叉树前中后层次遍历,递归实现

文章目录前序遍历代码\Python代码\C中序遍历代码\Python代码\C后序遍历代码\Python代码\C层序遍历代码\Python代码\C反向层序遍历代码\Python代码\C总结前序遍历 题目链接   前序遍历意思就是按照“根节点-左子树-右子树”的顺序来遍历二叉树&#xff0c;通过递归方法来实现…...

【RA4M2系列开发板GPIO体验2按键控制LED】

【RA4M2系列开发板GPIO体验2按键控制LED】1. 前言2. 配置工程2.1 新建FSP项目2.2 硬件连接以及FSP配置2.2.1 硬件连接2.2.2 FSP配置3. 软件实现3.1 实现的功能3.2 FreeRTOS使用3.2.1 Stack分配函数3.2.2 LED任务3.2.3 Key任务3.3 程序设计3.3.1 设置输出hex文件3.3.2 编译3.3.3…...

初步介绍CUDA中的统一内存

初步介绍CUDA中的统一内存 更多精彩内容: https://www.nvidia.cn/gtc-global/?ncidref-dev-876561 文章目录初步介绍CUDA中的统一内存为此&#xff0c;我向您介绍了统一内存&#xff0c;它可以非常轻松地分配和访问可由系统中任何处理器、CPU 或 GPU 上运行的代码使用的数据。…...

UVM实战--加法器

前言 这里以UVM实战&#xff08;张强&#xff09;第二章为基础修改原有的DUT&#xff0c;将DUT修改为加法器&#xff0c;从而修改代码以使得更加深入的了解各个组件的类型和使用。 一. 组件的基本框架 和第二章的平台的主要区别点 &#xff08;1&#xff09;有两个transactio…...

Linux系统点亮LED

目录应用层操控硬件的两种方式sysfs 文件系统sysfs 与/sys总结标准接口与非标准接口LED 硬件控制方式编写LED 应用程序在开发板上测试对于一款学习型开发板来说&#xff0c;永远都绕不开LED 这个小小的设备&#xff0c;基本上每块板子都至少会有一颗 LED 小灯&#xff0c;对于我…...

在superset中快速制作报表或仪表盘

在中小型企业&#xff0c;当下需要快速迭代、快速了解运营效果的业务&#xff0c;急需一款开源、好用、能快速迭代生产的报表系统。 老板很关心&#xff0c;BI工程师很关心&#xff0c;同时系统开发人员也同样关心&#xff0c;一个好的技术选型往往能够帮助公司减少很多成本&a…...

【可视化实战】Python 绘制出来的数据大屏真的太惊艳了

今天我们在进行一个Python数据可视化的实战练习&#xff0c;用到的模块叫做Panel&#xff0c;我们通过调用此模块来绘制动态可交互的图表以及数据大屏的制作。 而本地需要用到的数据集&#xff0c;可在kaggle上面获取 https://www.kaggle.com/datasets/rtatman/188-million-us…...

Obsidium一键编码作业,Obsidia惊人属性

Obsidium一键编码作业,Obsidia惊人属性 每个区域都包含几个可定制的功能&#xff0c;允许用户确定如何完全执行应用程序的安全性。Obsidia的功能区允许用户存储任何调整或一键编码作业。 Obsidia惊人属性&#xff1a; 代码虚拟化&#xff1a;代码虚拟化允许您转换程序代码的特定…...

约束优化:约束优化的三种序列无约束优化方法

文章目录约束优化&#xff1a;约束优化的三种序列无约束优化方法外点罚函数法L2-罚函数法&#xff1a;非精确算法对于等式约束对于不等式约束L1-罚函数法&#xff1a;精确算法内点罚函数法&#xff1a;障碍函数法等式约束优化问题的拉格朗日函数法&#xff1a;Uzawas Method fo…...

RocketMQ快速入门:消息发送、延迟消息、消费重试

一起学编程&#xff0c;让生活更随和&#xff01; 如果你觉得是个同道中人&#xff0c;欢迎关注博主gzh&#xff1a;【随和的皮蛋桑】。 专注于Java基础、进阶、面试以及计算机基础知识分享&#x1f433;。偶尔认知思考、日常水文&#x1f40c;。 目录1、RocketMQ消息结构1.1…...

FANUC机器人通过KAREL程序实现与PLC位置坐标通信的具体方法示例

FANUC机器人通过KAREL程序实现与PLC位置坐标通信的具体方法示例 在通信IO点位数量足够的情况下,可以使用机器人的IO点传输位置数据,这里以传输机器人的实时位置为例进行说明。 基本流程如下图所示: 基本步骤可参考如下: 首先确认机器人控制柜已经安装了总线通信软件(例如…...

[蓝桥杯 2015 省 B] 移动距离

蓝桥杯 2015 年省赛 B 组 H 题题目描述X 星球居民小区的楼房全是一样的&#xff0c;并且按矩阵样式排列。其楼房的编号为 1,2,3,⋯ 。当排满一行时&#xff0c;从下一行相邻的楼往反方向排号。比如&#xff1a;当小区排号宽度为 6 时&#xff0c;开始情形如下&#xff1a;我们的…...

反向传播:责任追溯大法——梯度如何“回流“

反向传播:责任追溯大法——梯度如何"回流"(Version B) 📚 《从零到一造大脑:AI架构入门之旅》专栏 专栏定位:面向中学生、大学生和 AI 初学者的科普专栏,用大白话和生活化比喻带你从零理解人工智能 本系列共 42 篇,分为八大模块: 📖 模块一【AI 基础概念…...

Phi-4-mini-reasoning效果对比:与Qwen-Math、DeepSeek-Math在逻辑题上的表现差异

Phi-4-mini-reasoning效果对比&#xff1a;与Qwen-Math、DeepSeek-Math在逻辑题上的表现差异 1. 模型介绍与测试背景 1.1 参测模型概览 本次对比测试聚焦三个专门针对数学和逻辑推理优化的模型&#xff1a; Phi-4-mini-reasoning&#xff1a;微软推出的轻量级推理专用模型&…...

intv_ai_mk11应用场景:为政府基层单位生成政策解读简报、为制造业写设备操作SOP、为律所起草合同条款草稿

intv_ai_mk11 AI对话机器人在专业场景的三大应用实践 1. 应用场景概览 intv_ai_mk11 AI对话机器人是一款基于7B参数Llama架构的智能助手&#xff0c;能够通过自然语言交互完成多种专业任务。本文将重点介绍其在三个专业领域的实际应用&#xff1a; 为政府基层单位生成政策解…...

Gemma-3 Pixel Studio快速上手:支持表格图像的结构化数据提取技巧

Gemma-3 Pixel Studio快速上手&#xff1a;支持表格图像的结构化数据提取技巧 1. 工具介绍与核心能力 Gemma-3 Pixel Studio是基于Google最新Gemma-3-12b-it模型构建的多模态对话终端&#xff0c;特别擅长处理包含表格的图像数据。与传统OCR工具不同&#xff0c;它不仅能识别…...

Zotero Better Notes终极指南:如何在笔记中创建流程图和思维导图

Zotero Better Notes终极指南&#xff1a;如何在笔记中创建流程图和思维导图 【免费下载链接】zotero-better-notes Everything about note management. All in Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-better-notes Zotero Better Notes是一款功能…...

OpenCore Legacy Patcher终极指南:老款Mac焕新升级的完整解决方案

OpenCore Legacy Patcher终极指南&#xff1a;老款Mac焕新升级的完整解决方案 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款…...

Gost透明代理终极指南:实现无感知网络流量转发 [特殊字符]

Gost透明代理终极指南&#xff1a;实现无感知网络流量转发 &#x1f680; Gost透明代理是一种强大的网络流量转发工具&#xff0c;能够实现完全无感知的网络代理体验。作为GO Simple Tunnel项目的核心功能&#xff0c;Gost透明代理让用户无需手动配置每个应用的代理设置&#x…...

编译期AI推理成为可能?C++27 constexpr增强深度解析,含Clang 19/MSVC 17.10实测基准数据,立即升级避坑指南

第一章&#xff1a;C27 constexpr函数增强的演进脉络与核心动机C27 对 constexpr 函数的扩展并非孤立演进&#xff0c;而是对自 C11 引入 constexpr、经 C14 放宽语义、C17 支持 if/switch 和局部变量、C20 引入 constexpr new/allocator 与虚拟函数等关键里程碑的系统性收敛与…...

模电设计实践之“音频功率放大器的设计” - 包含OCL主放大器设计、总电路图与框架详解、设计方...

模电设计实践之音频功率放大器的设计&#xff08;word文档&#xff09;文档有详细的参数计算过程 其主要内容是&#xff1a; 1、OCL主放大器的设计 2、总电路图、框架图以及单元电路介绍 3、设计方案论证 4、设计及电路参数计算&#xff0c;元器件选择 5、技术指标校验拆开音响…...

MinerU智能文档理解服务:专为高密度文本图像设计的轻量级解决方案

MinerU智能文档理解服务&#xff1a;专为高密度文本图像设计的轻量级解决方案 1. 引言&#xff1a;文档处理的智能化革命 在数字化办公时代&#xff0c;我们每天都要面对大量PDF文档、扫描件和图像资料。这些文件往往包含复杂的版面结构&#xff1a;多栏排版、嵌套表格、数学…...