理解虚拟dom

什么是虚拟dom?

虚拟 DOM是由一系列的 JavaScript 对象组成的树状结构,每个对象代表着一个DOM元素,包括元素的标签名、属性、子节点等信息。虚拟 DOM中的每个节点都是一个 JavaScript 对象,它们可以轻松地被创建、更新和销毁,而不涉及到实际的DOM操作。将目标所需的 UI 通过数据结构“虚拟”地表示出来,保存在内存中,然后将真实的DOM与之保持同步

主要作用

虚拟 DOM的主要作用是在数据发生变化时,通过与上一次渲染的虚拟 DOM进行对比,找出发生变化的部分,并最小化地更新实际 DOM。这种方式可以减少实际 DOM操作的次数,从而提高页面渲染的性能和效率。 总的来说,虚拟 DOM是一种用 JavaScript 对象模拟真实 DOM结构和状态的技术,它通过在内存中操作虚拟 DOM 树来减少实际 DOM操作,从而提高页面的性能和用户体验。

使用虚拟dom的优点?怎么去提高性能的

实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种GUI

减少 JavaScript 操作真实 DOM 的带来的性能消耗

最终都是去操作真实dom的为什么使用虚拟dom最终性能会好一点

当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程

而通过VNode,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attachDOM树上,避免大量的无谓计算

使用原生的API或者jQuery去操作DOM和基于虚拟DOM的框架(如Vue和React)去操作DOM,在性能上有一些差异:

  1. 直接操作DOM: 使用原生API或者jQuery直接操作DOM,每次操作都会直接影响真实的DOM树,这可能会引起浏览器的重排(reflow)和重绘(repaint),特别是在频繁地操作DOM时,性能开销较大。

  2. 虚拟DOM:虚拟dom是真实DOM的一个抽象表示。当状态变化时,框架会先在虚拟DOM上进行所有操作,然后通过算法比较新旧虚拟DOM的差异,并计算出最小的更新操作,最后批量更新到真实的DOM上。这种方式可以减少直接操作真实DOM的次数,从而提高性能。

  3. 批量更新: 在基于虚拟DOM的框架中,通常会采用异步批量更新的策略。这意味着当状态变化时,不会立即更新DOM,而是将更新操作放入一个队列中,稍后一次性执行,从而减少了重排和重绘的次数。内存批量操作 最终合并成一次更新操作

  4. 精确更新: 虚拟DOM框架在进行DOM更新时,通常会更加精确地只更新需要变化的部分,而不是整个组件或整个页面,这也有助于提高性能。

  5. 避免不必要的计算和渲染: 在某些情况下,组件的状态可能发生变化,但这并不影响其在DOM中的表示。使用虚拟DOM,如果检测到组件的输出没有变化,则可以跳过整个渲染和DOM更新过程。

什么时候性能更差呢?

  1. 极简的DOM操作: 对于非常简单或单次的DOM操作,使用虚拟DOM可能会引入不必要的性能开销。在这种情况下,直接使用原生DOM操作可能会更快,因为避免了创建虚拟DOM、比较差异和更新虚拟DOM这一系列步骤。

  2. 虚拟DOM树太大: 如果应用程序的组件树非常庞大,而且变化频繁,虚拟DOM的维护(创建、更新、比较)可能会成为性能瓶颈。每次状态更新时,虚拟DOM框架需要处理和比较大量的节点,这可能会导致性能下降。

  3. 频繁的大规模更新: 当应用程序需要频繁更新大部分或全部界面时,虚拟DOM的优势就不那么明显了。因为即使是虚拟DOM,大规模的更新仍然需要大量的计算来比较和更新节点。

  4. 不合理的使用模式: 如果开发者不遵循最佳实践,比如在应该使用组件局部状态的地方使用全局状态,或者不合理地频繁触发更新等,也可能导致虚拟DOM的性能下降。不恰当的使用方式会引起过多的虚拟DOM重新渲染,增加计算负担。

  5. 内存使用: 虚拟DOM需要在内存中维护一份当前DOM树的表示,对于内存受限的设备或应用,这可能成为一个问题。虽然现代设备的内存通常足够大,但在一些极端情况下,这仍然可能是一个考虑因素。

  6. 使用虚拟dom也不是所有情况都是最好 比如说基于jquery也会不好一点 

    额外开销:虚拟dom需要额外的内存存储虚拟节点,并且在更新时需要进行比较和差异计算。对于一些非常简单的操作,直接使用原生DOM或jQuery可能更快,因为避免了这些额外的开销。可能不兼容:jQuery和其他直接操作DOM的库可能会直接修改DOM元素,而React等使用虚拟DOM的框架会追踪这些元素的状态。如果同时使用这两种方法,可能会导致状态不一致,使得React无法准确地更新DOM。潜在的性能问题:如果在使用虚拟DOM的应用中大量使用jQuery进行DOM操作,可能会导致性能问题。因为每次jQuery操作后,虚拟DOM框架可能需要重新渲染整个组件树来保证界面的一致性,这会带来不必要的性能开销。

在Web应用的生命周期中,主要包含初始化(挂载)、更新(重新渲染)、卸载这几个阶段。虚拟DOM的使用在不同阶段带来的优势各有侧重:

初始化(挂载)过程可能虚拟dom会让他性能变差:构建一整个虚拟dom树在转化真实dom 可能有一些性能开销

  • 构建虚拟DOM树:在应用首次加载时,框架需要根据组件的结构和状态构建整个虚拟DOM树。这个过程涉及到创建大量的虚拟DOM节点,并且可能包括复杂的计算和逻辑判断。

  • 虚拟DOM到真实DOM的转换:构建完成虚拟DOM树后,框架需要将其转换为真实的DOM节点,并将这些节点插入到DOM树中。这个过程涉及到浏览器的DOM操作,可能会触发重排和重绘,导致性能开销。

  • 初始化渲染的性能影响:对于大型应用或复杂界面,初始化渲染过程中涉及的虚拟DOM操作和真实DOM操作可能会比较耗时,从而影响应用的启动速度和用户体验。

虽然虚拟DOM在更新过程中可以提高性能,但在初始化渲染阶段,它确实引入了一些额外的开销。为了优化这一过程,开发者可以采取一些措施,如代码分割(Code Splitting)、服务端渲染(Server-Side Rendering)或增量静态生成(Incremental Static Generation),以减少首次加载时的资源量和提高渲染效率。

更新(重新渲染)过程

当应用状态变化时,需要更新UI以反映这些变化。这个阶段是虚拟DOM最能发挥优势的地方:

  • 差异比较(Diffing):虚拟DOM框架通过比较新旧虚拟DOM树的差异,只更新实际变化的部分,而不是重新渲染整个UI。

  • 批量和异步更新:许多虚拟DOM框架会集中处理更新,通过异步或批量更新的方式减少对实际DOM的操作次数,从而提高性能。

卸载过程

当组件或整个应用不再需要时,进行清理操作。虚拟DOM在这个阶段的优势不如前两个阶段明显,因为主要工作是清除和解除绑定,避免内存泄露。不过,使用虚拟DOM框架可以简化这个过程,因为框架通常会自动处理组件的清理工作。

新旧dom的对比找出差异 这个对比是怎么对比的呢?

在React中,新旧DOM的对比  是通过虚拟DOM来实现的。React维护了一个轻量级的虚拟DOM树来表示实际的DOM结构。当组件状态或属性发生变化时,React会创建一个新的虚拟DOM树,并将其与之前的虚拟DOM树进行对比,以找出实际需要更新的部分。这个对比过程大致分为以下几个步骤:

  1. 树的对比:React首先比较两棵树的根节点。如果根节点的类型不同(比如一个是<div>,另一个是<span>),React会直接删除旧树并完整地构建新树。如果根节点类型相同,React会继续比较它们的子节点。

  2. 元素类型的对比:对于同一层级的一组子节点,React会根据元素的类型进行比较。如果元素类型(比如标签名、组件类型)改变了,React会替换整个元素及其子元素。如果元素类型相同,React会保留该元素,并继续比较其属性和子元素。

  3. 属性的对比:对于同一元素的属性,React会比较新旧属性集合的差异,并仅更新变化的属性。这包括样式、事件处理器等。

  4. 列表的对比:对于列表元素,React使用key属性来识别每个列表项的唯一性。有了key,React可以更准确地判断哪些元素是新增的、哪些被移除了、哪些只是位置变化了,从而优化列表的渲染性能。

  5. 递归对比子节点:React会递归地对比每个子节点,并应用上述规则。这个过程会一直进行,直到所有节点都被比较完毕。

通过这种方式,React能够精确地确定需要进行实际DOM更新的最小集合,从而提高渲染效率。这个过程是自动进行的,开发者通常不需要直接参与其中。

react vue diff算法 的区别

Diff算法时间复杂度是O(n)

react实现O(n)的方式:

react 将 diff 算法优化到 O(n) 的时间复杂度,基于了以下三个前提策略:

1.只对同级元素进行比较。如果出现跨层级的 dom 节点更新,则不进行复用。 深度优先遍历

2.两个不同类型的组件会产生两棵不同的树形结构,React会认为这两棵树完全不同,直接替换旧的树。类型不同,整个删除

3.key属性的使用:对于列表中的元素,React使用key属性来识别每个元素的唯一性。有了key,React可以更准确地判断哪些元素是新增的、哪些被移除了、哪些只是位置变化了。

上面的三种 diff 策略,分别对应着 tree diff、component diff 和 element diff。

Vue实现O(n)的方式

Vue在进行虚拟DOM的Diff算法时,也采用了一些策略来优化性能:

  1. patch函数:Vue使用一个名为patch的函数来比较新旧虚拟DOM节点,并应用差异到真实DOM上。这个过程是递归的,但Vue通过一些优化策略减少了不必要的比较。

  2. 双端比较算法:在比较列表中的元素时,Vue采用了一种双端比较的算法。这个算法会同时从列表的头部和尾部开始比较,通过移动头尾指针来减少比较的次数。

  3. key属性的使用:和React类似,Vue也推荐为列表中的每个元素设置一个唯一的key属性。这样可以更快地识别和定位节点的变化。

  4. 静态元素的优化:Vue会跳过对静态元素和静态子树的比较,因为它们不会发生变化。这进一步减少了比较的范围。

vue和react的diff算法都是进行同层次的比较,主要有以下两点不同:

1.vue对比节点,如果节点元素类型相同,但是类名不同,认为是不同类型的元素,会进行删除重建,但是react则会认为是同类型的节点,只会修改节点属性。

2.vue的列表比对采用的是首尾指针法(也就是双端比较),而react采用的是从左到右依次比对的方式(深度优先,单向比较),当一个集合只是把最后一个节点移动到了第一个,react会把前面的节点依次移动,而vue只会把最后一个节点移动到第一个,从这点上来说vue的对比方式更加高效。

在 Vue 3 中,diff是指在进行虚拟 DOM 更新时,对比新旧虚拟 DOM 树的差异,然后只对实际发生变化的部分进行更新,以尽可能地减少对真实 DOM 的操作,提高页面的性能和效率diff整体策略为:深度优先,同层比较。也就是说,比较只会在同层级进行, 不会跨层级比较;比较的过程中,循环从两边向中间收拢。高效地处理虚拟 DOM 树的更新,使得页面在数据变化时能够快速响应并更新对应的视图。

React 的 Diff 算法并不会对整个树进行比较,而是采用一种深度优先、单向的比较策略。 在比较过程中,React 会标记节点的更新状态,将差异记录在变更集合中。 最终,React 会根据变更集合对实际 DOM 进行最小化的更新,以提高性能。

总的来说,Diff 算法的核心思想是Diff就是将新老虚拟DOM的不同点找到并生成一个补丁,并根据这个补丁生成更新操作,以最小化对实际 DOM 的操作,提高页面渲染的性能和效率。

react的虚拟dom是怎么进行数据渲染的?

React的虚拟DOM是其高效数据渲染的核心机制之一。虚拟DOM是一个轻量级的JavaScript对象,它是真实DOM的一个抽象表示。React使用虚拟DOM来优化渲染流程,减少对实际DOM的操作,从而提高应用的性能。下面是React通过虚拟DOM进行数据渲染的主要步骤:

  1. 创建虚拟DOM:当一个React组件渲染时,基于其当前的状态(state)和属性(props),React会构建一个虚拟DOM树。这个树是由虚拟DOM元素(React元素)组成的,它们是JavaScript对象,反映了组件应该如何在页面上呈现。

  2. 渲染虚拟DOM:React将这个虚拟DOM树转换成真实DOM节点,并将其挂载到浏览器的DOM中。这一步是在组件第一次渲染时发生的,称为“挂载”(mounting)。

  3. 状态更新:当组件的状态(state)或属性(props)发生变化时,React将基于新的状态和属性创建一个新的虚拟DOM树。

  4. 虚拟DOM比较(Diffing):React通过比较新旧两个虚拟DOM树来确定实际变化的部分。这个过程称为“对比”(diffing),它通过一系列的算法优化,尽量减少需要更新的节点数量。

  5. 更新真实DOM:一旦React知道了哪些虚拟DOM节点发生了变化,它将这些变化映射到真实DOM上。这个过程称为“提交”(committing)。React会尽量高效地更新DOM,只改变需要变化的部分,而不是重新渲染整个组件树。

  6. 批量更新和异步渲染:React有能力将多个状态更新合并成一个批量更新,以减少对虚拟DOM树的重新构建次数和对真实DOM的操作次数。React 16引入的Fiber架构还允许异步执行渲染任务,使得大型应用的性能得到了进一步的提升。

通过以上步骤,React的虚拟DOM机制使得应用能够以高效和优化的方式进行数据渲染和界面更新。这种方法最大限度地减少了DOM操作的数量,因为真实的DOM操作是Web应用中最耗性能的部分之一。

在 Vue.js 中,一系列操作指的是将虚拟 DOM 树映射到真实 DOM 的过程,这个过程通常包括以下几个主要步骤:
1.创建 VNode 树:

首先,Vue.js 根据组件的模板或者 render 函数生成虚拟 DOM 树,每个节点都是一个 VNode 对象,描述了真实 DOM 的结构。


3.更新 VNode 树:

当 Vue 组件的状态发生变化时,或者父组件重新渲染时,Vue 会重新生成一颗新的 VNode 树。这个新的 VNode 树会与之前的 VNode 树进行比较,找出两棵树之间的差异。


5.比较差异:

Vue.js 的虚拟 DOM 算法会比较新旧两棵 VNode 树之间的差异,找出哪些地方需要更新、删除或者新增 DOM 节点。


7.生成更新补丁:

将差异比较的结果抽象成一系列的更新操作,称为补丁(patch),这些补丁描述了如何将旧的 VNode 树更新到新的 VNode 树。


9.应用更新补丁:

Vue.js 将这些补丁应用到真实的 DOM 上,通过一系列的 DOM 操作(添加、修改、删除节点)来实现新旧 VNode 树的同步。


11.渲染真实 DOM:

最终,通过以上操作,Vue.js 将虚拟 DOM 树中的更新映射到真实的 DOM 上,从而实现页面的更新和重绘。

这一系列操作在 Vue.js 内部自动完成,开发者无需手动操作。Vue.js 的虚拟 DOM 算法会尽可能地优化这些操作,以提高页面渲染的性能和效率。通过虚拟 DOM 的这种方式,Vue.js 实现了高效的页面更新,提高了开发效率,同时也保证了页面的性能。

怎么实现虚拟dom

createElement 创建 VNode 的过程,每个 VNode 有 childrenchildren 每个元素也是一个VNode,这样就形成了一个虚拟树结构,用于描述真实的DOM树结构

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

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

相关文章

弧形导轨在自动化设备中的传动原理

在自动化机械系统中&#xff0c;弧形导轨是一种常见的轨道结构&#xff0c;用于支撑和引导物体沿着指定的弧线运动。其工作原理基于几何学和物理学的原理。 弧形导轨通常由一个弧形的轨道和一个移动部件组成。轨道一般呈弧形&#xff0c;其几何形状可以是圆弧、椭圆弧等&#x…

Java(2)之变量,数据类型,运算符

1、标识符 在java中标识符是由字母数字下划线&#xff0c;美元符号组成&#xff08;其中数字没办法作首&#xff09;在java中是区分大小写的。 2、关键字 关键字是在java中赋予了特殊的含义的字符&#xff0c;只能用于特定地方 例如包package 类class 接口interface 引用 &a…

智慧工地整体解决方案(3)

塔吊安全管理系统 需求分析 塔式起重机是现代施工中必不可少的关键设备,是施工企业装备水平的标志性重要装备之一。随着近年来建筑行业塔机的大量使用,由于塔机违规超限作业和塔机群干涉碰撞等引发的各类塔机运行安全事故频繁发生,造成了巨大的生命财产损失。 典型事故现…

Linux 设备树: 设备树节点与属性在 dtb 文件中的存储

前言 当前新版本的 Linux 内核 设备驱动框架&#xff0c;与设备树&#xff08;Device Tree&#xff09;结合密切&#xff0c;整体 设备树的设备驱动框架&#xff0c;比较的庞大&#xff0c;但又非常的经典。 一个个的 设备树解析函数&#xff0c;都是前人【智慧】的结晶&#…

【Golang星辰图】解密数据序列化:探索Go语言中的数据序列化库,提升开发效率

提升效率&#xff1a;了解Go语言中的高效数据序列化解决方案 前言 Go语言作为一门流行的编程语言&#xff0c;其生态系统中涵盖了许多强大且高效的数据序列化库。本文将深入探索Go语言的几个著名数据序列化库&#xff0c;包括go-msgpack、go-bson、go-base58、go-json、go-xm…

【pysurvival Python 安装失败】

这个错误与 sklearn 包的名称更改有关&#xff0c;导致 pysurvival 在构建元数据时失败。现在&#xff0c;你需要修改 pysurvival 的安装文件以使用正确的 scikit-learn 包名 编辑安装文件&#xff1a;找到 pysurvival 的安装文件&#xff0c;可能是 setup.py 或 pyproject.to…

2024系统架构师---隐式调用架构风格的概念与应用

隐式调用架构风格&#xff0c;也被称为事件驱动架构&#xff0c;是一种软件架构模式&#xff0c;其中组件间的交互是基于事件的&#xff0c;而不是直接的调用。这种架构风格侧重于系统中的事件生成、事件监听和事件处理&#xff0c;使组件间的耦合度降低&#xff0c;提高了模块…

智慧公厕:改变城市生活的革命性基础设施

在现代城市的高品质生活要求背景下&#xff0c;公共厕所成为了不可或缺的基础设施。然而&#xff0c;传统的公厕在服务质量、管理效率方面存在一定的问题。为了提供更好的公厕服务&#xff0c;智慧公厕应运而生。通过智能化的管理模式&#xff0c;智慧公厕实现了公厕使用与管理…

玩转ChatGPT:Suno制作音乐

AI开始进军音乐领域了。 一款音乐AI神器——Suno V3发布&#xff0c;它能够处理从间奏到主歌、副歌、桥段直至尾奏的完整结构&#xff0c;零门槛创作音乐。 需要科学上网&#xff0c;官方网站&#xff1a;https://app.suno.ai/ 使用GPT写个歌词&#xff0c;然后丢进Suno生成…

Web APIs知识点讲解(阶段七)

正则表达式 1.能够利用正则表达式校验输入信息的合法性2. 具备利用正则表达式验证小兔鲜注册页面表单的能力 一.正则表达式 1.正则表达式 正则表达式&#xff08;Regular Expression&#xff09;是用于匹配字符串中字符组合的模式。在 JavaScript中&#xff0c;正则表达式也…

关于yolov8x6.yaml的一些理解

下面是yaml的内容: # Ultralytics YOLO 🚀, AGPL-3.0 license # YOLOv8 object detection model with P3-P6 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters nc: 80 # number of classes scales: # model compound scaling const…

光明源@智慧厕所公厕软件系统有哪些核心功能?

在现代城市的建设中&#xff0c;智慧公厕的建设成为了提升城市品质和居民生活质量的重要举措。而智慧公厕的核心&#xff0c;不仅仅在于其硬件设备的智能化&#xff0c;同样重要的是其背后支持的智慧厕所公厕软件系统。让我们一起探讨&#xff0c;智慧厕所公厕软件系统有哪些核…

Spring面试题系列-6

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而&#xff0c;Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言&#xff0c;绝大部分Java应用都可以从Spring中受益。 Spring中的单…

ESP32烧录固件(二种方法)

在选择不同固件时可根据我们的需要选择合适的固件&#xff0c;还需根据开发板Flash的内存大小选择&#xff0c;查看Flash的内存大小&#xff0c;可查阅下面的第二种方法中查看开发板信息。 官方固件 MicroPython - 用于微控制器的Python https://micropython.org/download/ESP…

主函数的三个参数

1).主函数的三个参数的含义: argc:主函数的参数个数 argv:主函数的参数内容 envp:环境变量; 2).演示代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc,char *argv[],char *envp[]) { int i0;printf("argc%d\n&…

API接口开发1688阿里巴巴官方API接口获得店铺详情1688.seller_info-API接入演示

要获取店铺详情&#xff0c;你需要使用1688API接口。以下是一个简单的Python示例&#xff0c;展示了如何使用requests库调用阿里巴巴API并解析返回的数据&#xff1a; # coding:utf-8 """ Compatible for python2.x and python3.x requirement: pip install re…

【C++】开散列实现unordered_map与unordered_set的封装

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;手撕哈希表的闭散列和开散列 > 毒鸡汤&#xff1a;谁不是一边受伤&#xff0c;一边学会坚强。 > 专栏选自&#xff1a;C嘎嘎进阶 > 望小伙伴们…

第十五届蓝桥杯第二期模拟赛——python

第一题 填空题 1、问题描述 小蓝要在屏幕上放置一行文字&#xff0c;每个字的宽度相同。 小蓝发现&#xff0c;如果每个字的宽为 36 像素&#xff0c;一行正好放下 30 个字&#xff0c;字符之间和前后都没有任何空隙。 请问&#xff0c;如果每个字宽为 10 像素&#xff0c;字符…

c语言例题,实现一个整型有序数组的二分查找

c语言中&#xff0c;有很多可以实现效果的方法&#xff0c;而在一个整型有序的数组中&#xff0c;我们可以使用二分查找的方法来实现对于一个数组中的元素查找。二分查找的优点在于本身需要的计算是比较少的&#xff0c;一次计算查找排除掉数组中一半的元素&#xff0c;尤其对于…

HaDoop学习1

第一章 读时模式&#xff08;Read-Time Schema&#xff09;- 写时模式&#xff08;Write-Time Schema&#xff09; 通常与模式演变&#xff08;Schema Evolution&#xff09;相关 即在数据表结构发生变化时&#xff0c;已经存在的数据如何适应新的模式&#xff1f; 【读时模…