虚拟DOM是什么
参考文章做的总结,如有不足之处请指正!
在讲虚拟dom之前,先讲讲,为什么前端操作dom会导致页面性能降低?
先说几个概念 有助于后面的理解
什么是 JavaScript 引擎?
JavaScript引擎是一个专门处理JavaScript脚本的虚拟机,
能够将 Javascript 代码处理并执行的运行环境
什么是渲染引擎?
渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。这是每一个浏览器的核心部分,所以渲染引擎也称为浏览器内核。它负责取得网页的内容(HTML、XML、图象等等)、整理信息(例如加入CSS等),以及计算网页的显示方式然后会输出至显示器
浏览器的渲染机制
1、从下载文档到渲染页面的过程中,浏览器会通过解析HTML文档来构建DOM树,解析CSS产生CSS规则树(CSSOM)。
2、渲染过程中,如果遇到<script>就停止渲染,执行JS代码。因为浏览器有GUI渲染线程与JS引擎线程,为了防止渲染出现不可预期的结果,这两个线程是互斥的关系。 JavaScript的加载、解析与执行会阻塞DOM的构建。
3、之后根据DOM树和CSS规则树构建渲染树(Render-Tree),在这个过程中CSS会根据选择器匹配HTML元素。渲染树包括了每个元素的大小、边距等样式属性,渲染树中不包含设置为 display: none; 的隐藏元素及<head>、<script>等不可见元素(但是对于visibility: hidden;或opacity: 0;的元素,它们会占据屏幕空间,因此它们将出现在渲染树中)。 最后浏览器根据元素的坐标和大小来计算每个元素的位置,并绘制这些元素到页面上。
JavaScript中 js 引擎和渲染引擎(浏览器内核)是独立实现的。使用 js 去操作 DOM 时,本质上是 JS 引擎和渲染引擎之间进行了“跨界交流”。每操作一次 DOM,都要跨界一次。跨界的次数一多,就会产生比较明显的性能问题。
在浏览器中,DOM的实现和ECMAScript的实现是分离的。比如在Chrome中使用WebKit中的WebCore处理DOM和渲染,但ECMAScript是在V8引擎中实现的。所以通过JavaScript代码调用DOM接口,相当于两个独立模块的交互。相比较在同一模块中的调用,这种跨模块的调用其性能损耗是很高的。
DOM操作通常会导致浏览器的重绘(repaint)和回流(reflow,也叫重布局),重绘和回流的代价很高。**
重绘指的是页面的某些部分要重新绘制,比如颜色或背景色的修改,元素的位置和尺寸并未改变。
回流则是元素的位置或尺寸发生了改变,浏览器需要重新计算渲染树,导致渲染树的一部分或全部发生变化;渲染树重新建立后,浏览器再重新绘制页面上受影响的元素。
回流的代价比重绘的代价高很多,重绘不一定是因为回流,但回流一定会导致重绘。
浏览器渲染页面流程 参考
JS操作DOM为什么会影响性能?
正是因为这样 才会引入虚拟dom
虚拟DOM的意义就在于使找出差异的性能消耗最小化,直接操作DOM的性能开销是庞大的,
但是即便是使用虚拟DOM,最终还是要改变真实DOM,也就是说必要的DOM操作是不可避免的,
而虚拟DOM则通过它的diff算法使得DOM的更新范围尽可能变小,降低了真实DOM操作的性能开销,
同时通过框架的封装给开发者提供了一种更友好的声明式的前端开发方式
下面举个例子 操作真实dom和虚拟dom的区别:比如 有A、B、C、D四个人。
先让A站第一个,在让B站第二个,C站第三个,但是我最后让D站第一个,然后其他就往后移
(直接操作真实的DOM节点的话,浏览器会一个一个从头到尾执行一边)这样其他三个人之前的排位置的时间算是白花了,还要往旁边挪开,空出一个位置给D。
四个人还好,但是要是四百个人呢,399个人需要移动位置,真的是有点浪费时间和精力了。
所以那有没有更好的办法呢?
这个时候虚拟DOM就显得更加优秀了。虚拟DOM是一个js对象。怎么理解这个js对象呢?
我们都知道对象使用之前要定义,不定义直接使用的话,就会报错。也就是说是用不了。
而这个虚拟DOM呢,就像是一个空对象,操作虚拟DOM就像是网这个对象里面添加属性和对应的属性值。
对象内的属性全部定义好了之后,再按照这个对象里面的内容,全部转化,输送给真实的DOM,让其在页面中渲染出来。因为这个对象不可能一直保持不变,在开发中出现代码的增删改是很正常的现象。
操作的是虚拟DOM,那是所以只要对象一改动,就能马上反应到虚拟DOM上。那又是如何反应的呢?
这里面又牵扯到一个概念就是diff算法。
反应的方式就是通过diff算法来实现的。对象更新时会生成一个新DOM对象,diff算法就是把新的DOM对象和老的DOM对象进行比较,1、发现新属性里没有老属性,那么老属性就直接卸载;新属性直接安装
2、发现新属性的和老属性全部相同(属性值也有可能是对象,也要往下面核对),那么就保留
3、发现同一个属性里,新和老的有些值不同,那么则要排列比较,看哪些修改了,哪些是新增的,哪些是删除的。
这样在一定程度上也比更深的遍历发现同更加节约时间。因为老对象的改变,则会使真实的DOM也会发生改变,这样就在页面上实现了刷新在上面3的内容中,我们又可以得到一个知识点:那就是虚拟DOM的key值。
(Vue2 的模板语法,即被写在 <template> 标签内的所有 HTML 标签,并非直接展示在页面上,而是会先被 Vue 进行解析,生成虚拟DOM节点,之后再由虚拟DOM转为真实DOM,真实DOM才会真正显示在页面上。在虚拟DOM转换的过程中,如何提升解析效率?便是通过 key。)key值就相当于给这些属性值加上了一个标签,这样我们就可以通过这个key值去找到对应的值与之比较或是别的操作。所以,这里我们就要求key值最好是独一无二的。如果用index作为key值得话,如果值得位置有变动,那么对应的index指向的就是变动后的值,所以变动后的值的位置和原来的位置是不是一样,不能确定因此,index作为key值会有可能会存在一定偏差。
看一下页面渲染的流程:解析HTML -> 生成DOM -> 生成 CSSOM -> Layout -> Paint -> Compiler
下面对比一下修改DOM时真实DOM操作和Virtual DOM的过程,来看一下它们重排重绘的性能消耗
真实DOM∶ 生成HTML字符串+重建所有的DOM元素
虚拟DOM∶ 生成vNode+ DOMDiff+必要的dom更新
<!--这是普通的Html标签写法->
<a class="link" href="https://github.com/facebook/react">React<a>
//这是在js中手动生成相同dom的写法
var a = document.createElement('a')
a.setAttribute('class', 'link')
a.setAttribute('href', 'https://github.com/facebook/react')
a.appendChild(document.createTextNode('React'))
//这是一种封装,沿用的React.createElement的命名
var a = React.createElement('a', {className: 'link',href: 'https://github.com/facebook/react'
}, 'React')
React.createElement 的方法名,看似创建了一个Element,实质只是一个轻量级的数据结构,其最简形式如下
var a = {type: 'a',props: {children: 'React',className: 'link',href: 'facebook/react · GitHub'},_isReactElement: true
}React.render(a, document.body)
React.render(ReactElement, DOM) 中所谓的 ReactElement,是指私有属性_isReactElement 为 true 的一种数据结构,而非真正的Element。
所有html结构,都可以用js dom来构造,而且能将构造的步骤封装起来,做到「数据-dom结构」的映射。缓存初始数据,新数据进来时,与旧数据对比,找到差异,根据差异本身的性质进行dom操作;无差异,则不作为。dom本身在js中就是一种数据结构,console.dir(document.body),在控制台可以看到body的数据结构。然而,dom相关的数据丰富而且复杂,我们其实只关心少数元素的少数属性。建立一个javascript plain object,非常轻量,用它保存我们真正关心的与dom相关的少数数据;对它进行操作,然后对比操作前后的差异,再根据映射关系去操作真正的dom,无疑能提高性能。这就是虚拟DOM的理念。
加入虚拟dom之后的浏览器更新
1、将页面改变的内容应用到虚拟 DOM 上,而不是直接应用到 DOM 上;
2、变化被应用到虚拟 DOM 上时,虚拟 DOM 并不急着去渲染页面,而仅仅是调整虚拟 DOM 的内部状态,这样操作虚拟 DOM 的代价就变得非常轻了。
3、在虚拟 DOM 收集到足够的改变时,再把这些变化一次性应用到真实的 DOM 上。
这里参考vue中如何将虚拟dom转为真实dom
超级推荐看这个 小白也能懂的 vue是如何渲染虚拟dom到dom上的
虚拟dom的缺点
1、首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,会比 innerHTML 插入慢。代码更多,体积更大
2、内存占用增大
3、 小量的单一的dom修改使用虚拟dom成本反而更高,不如直接修改真实dom快
这篇文章是翻阅资料后得到的总结
相关文章:

虚拟DOM是什么
参考文章做的总结,如有不足之处请指正! 在讲虚拟dom之前,先讲讲,为什么前端操作dom会导致页面性能降低? 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎? JavaScript引擎是一个专门处理JavaScript脚…...

进程通信方式
无名管道( pipe ): 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。高级管道(popen): 将另一个程序当做一个新的进程在当前程序进…...

强化学习基础知识
强化学习是一种机器学习方法,通过agent与environment的互动,学习适当的action policy以取得更大的奖励reward。本篇博客介绍强化学习的基础知识,与两类强化学习模型。 目录强化学习的基础设定policy based 强化学习的目标3个注意事项实际训练…...

LeetCode230218_148、654. 最大二叉树
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…...
WordPress 是什么?.com 和 .org 的 WordPress 有什么差异?
本篇文章会介绍这次WordPress 5.8核心版本所带来的其中一项新功能:内存块小工具(Widget)此次更新把小工具编辑设定的页面也改成用「内存块编辑」的概念,就跟内置的「古腾堡」编辑器一样,把所有元件都内存块化ÿ…...

java8新特性【2023】
Lambda表达式 新的一套语法规则 是一个匿名函数 Testpublic void test1(){Runnable r1 new Runnable(){Overridepublic void run() {System.out.println("线程A");}};r1.run();System.out.println("");Runnable r2 () -> System.out.println("…...
刷题记录:牛客NC51101Lost Cows
传送门:牛客 题目描述: (2≤N≤8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood watering hole and drank a few too many beers before dinner. When it was time to line up for their ev…...
华为OD机试 - 不等式 | 备考思路,刷题要点,答疑 【新解法】
最近更新的博客 华为OD机试 - 寻找路径 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最小叶子节点 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 对称美学 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】华…...

GuLi商城-SpringCloud-OpenFeign测试远程调用
1. Feign 简介 Feign 是一个声明式的 HTTP 客户端,它的目的就是让远程调用更加简单。Feign 提供了HTTP请 求的模板,通过编写简单的接口和插入注解,就可以定义好 HTTP 请求的参数、格式、地址等信 息。Feign 整合了 Ribbon(负载…...

阿里云_山东鼎信短信的使用(云市场)
目录山东鼎信API工具类随机验证码工具类进行测试Pom依赖(可以先导入依赖)创建controllerSmsServiceSmsServiceImplswagger测试(也可以使用postman)山东鼎信API工具类 山东鼎信短信官网 找到java的Api,复制下来 适当改了一下,为了调用(类名SmsUtils) p…...

基于虚拟机机的代码保护技术
虚拟机保护技术是基于x86汇编系统的可执行代码转换为字节码指令系统的代码,以达到保护原有指令不被轻易逆向和篡改的目的。 字节码(Byte-code)是一种包含执行程序,由一序列 op 代码/数据对组成的 ,是一种中间码。字节是…...

Win10耳机有声音麦不能说话怎么办?麦克风说话别人听不到解决方法
网上找了一些解决办法,一般都是重复的,几个设置调来调去也就那样,没什么用 这种问题一般是“老式”一点的台式机会出现,提供的解决办法如下: 首先下载带面板的音频管理器,如realtek高清晰音频管理器&…...
The 22nd Japanese Olympiad in Informatics (JOI 2022/2023) Final Round 题解
交题:https://cms.ioi-jp.org/documentation A 给一个序列 a1,⋯,ana_1,\cdots,a_na1,⋯,an。 执行nnn个操作,第iii个操作为找出第iii个数前离其最近且与它相同的数的位置,把这两个数之间的数全部赋值aia_iai。求最后的序列。 考虑第…...

openEuler RISC-V 成功适配 VisionFive 2 单板计算机
近日,RISC-V SIG 成功在 VisionFive 2 开发板上适配欧拉操作系统,目前最新版本的 openEuler RISC-V 22.03 V2 镜像已在 VisionFive 2 开发板上可用,这是 openEuler 推动 RISC-V 生态演进的又一新进展。下载链接https://mirror.iscas.ac.c…...

2005-2022中国企业对外直接投资、OFDI海外投资明细、中国全球投资追踪数据CGIT(含非建筑施工类问题投资)
中国全球投资跟踪”(China Global Investment Tracker),数据库,美国企业研究所于1月28日发布。数据库显示,2005年以来,中国对外投资和建设总额已接近2万亿美元。该数据库是唯一一套涵盖中国全球投资和建设的…...

PCB学习笔记——使用嘉立创在线绘制原理图与PCB
嘉立创软件地址:https://lceda.cn/ 新建工程-新建原理图,在元件库中可以搜索元器件,可以直接放置在原理图上。 原理图绘制完成后,保存文件,设计-原理图转PCB,可以直接生成对应的PCB,设置边框&…...

【C++】类型转化
🌈欢迎来到C专栏~~类型转化 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&…...
Mybatis -- resultMap以及分页
查询为null问题 要解决的问题:属性名和字段名不一致 环境:新建一个项目,将之前的项目拷贝过来 1、查看数据库的字段名 2、Java中的实体类设计 public class User { private int id; //id private String name; //姓名 private String passwo…...

Linux之进程
一.冯诺依曼体系 在计算机中,CPU(中央处理器)是不直接跟外部设备直接进行通信的,因为CPU处理速度太快了,而设备的数据读取和输入有太慢,而是CPU以及外设直接跟存储器(内存)打交道&am…...

结构体——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是结构体噢,之前我们在初始C语言中其实就已经学习过了结构体的知识,但是不是很全面,这次,我们也只是稍微详细一点,敬请期待小雅兰之后的博客ÿ…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...