关于虚拟DOM

news/2025/3/28 8:08:37/文章来源:https://www.cnblogs.com/lxl0419/p/18782634

1、前置信息

    由于页面重排与重绘的问题,浏览器处理DOM比较慢,如果页面比较复杂,频繁的操做DOM会造成很大的开销

    传统的Web应用中,数据的变化会实时地更新到用户界面中,于是每次数据微小的变化都会引起DOM的渲染。

    而虚拟DOM是将所有的操作聚集到一块,计算出所有的变化后,统一更新一次虚拟DOM

    一个页面如果有100次变化,真实DOM的就会渲染100次,而虚拟DOM只需要渲染一次,从这点上来看,页面越复杂,虚拟DOM的优势越大

tips:

  1. React的核心是JSX语法,JSX就是JS上的扩展,是一个拥有javascript全部功能的模板语言。通过Babel去对JSX进行转化为对应的JS对象,最终展示到浏览器
  2. react组件首字母大写:Babel去对JSX进行转化时,判断是原生DOM标签,还是React组件,就是根据标签的首字母,小写为原生标签,大写是React组件
  3. React.Fragment:在React中,组件是不允许返回多个节点的,等价于<></>,实际上是没有节点的,创建虚拟DOM时:React.createElement(React.Fragment, null, ""),实际上<React.Fragment>允许有key的,而<></>无法附上key

2、什么是虚拟DOM

   虚拟DOM实际上就是对象

    <div className='Index'><div>哈喽</div><ul><li>React</li><li>Vue</li></ul></div>
// 转化为虚拟DOM{type: 'div',props: { class: 'Index' },children: [{type: 'div',children: '夏目'},{type: 'ul',children: [{type: 'li',children: 'React'},{type: 'li',children: 'Vue'},]}]}// type:实际的标签
// props:标签内部的属性(除key和ref,会形成单独的key名)
// children: 为节点内容,依次循环


// 从结构上来说,虚拟DOM并没有真实DOM上绑定的很多属性和方法,因此,就算直接把虚拟DOM删除后,重新建一个也是非常快的

// 可以通过console对比查看
 const VDOM = React.createElement('div', {}, '虚拟')
 const DOM = document.createElement("div");
 DOM.innerHTML = '真实'
 console.log(`虚拟DOM:`, VDOM)
 console.log(`真实DOM:`, DOM)

  

3、虚拟DOM的优点(浏览器在处理DOM的时候会很慢,处理JavaScript会很快)

  1. 效率:React会通过虚拟DOM来确保DOM的匹配,如何操作DOM,更新DOMReact会处理好,只需要关注业务逻辑
  2. 性能:
    1、React会将整个DOM保存为虚拟DOM,如果有更新,会维护两个虚拟DOM,来比较之前的状态当前的状态,并会确定哪些状态被修改,然后将这些变化更新到实际DOM上,一旦真正的DOM发生改变,也会更新UI
    2、所以在虚拟DOM发生变化的时候,只会更新局部,而非整体。同时,虚拟DOM减少了非常多的DOM操作,所以性能会提升
  3. 优势:
    1、优势是在于diff算法批量处理策略,将所有的DOM操作搜集起来,一次性去改变真实的DOM
    2、但在首次渲染上,虚拟DOM会多了一层计算,消耗一些性能,所以有可能会比html渲染的要慢
    3、虚拟DOM实际上是找了一条最短,最近的路径,并不是说比DOM操作的更快,而是路径最简单

4、兼容性 

  1. React基于虚拟DOM实现了一套自己的事件机制,并且模拟了事件冒泡和捕获的过程,采取事件代理批量更新等方法,满足各个浏览器的事件兼容性问题
  2. 对于跨平台,ReactReact Native都是根据虚拟DOM画出相应平台的UI层,只不过不同的平台画法不同

5、如何实现虚拟DOM

  1. JSX代码会被转为React.createElement的形式
  2. React.createElement:它的功能是将props子元素进行处理后返回一个ReactElement对象(keyref会特殊处理)

    ReactElement这个对象会将传入的几个属性进行组合并返回

    • type:实际的标签
    • props:标签内部的属性(除keyref,会形成单独的key名)
    • children: 为节点内容,依次循环
    • type:实际的标签,原生的标签(如'div'),自定义组件(类或是函数式)
    • props:标签内部的属性(除keyref,会形成单独的key名)
    • key:组件内的唯一标识,用于Diff算法
    • ref:用于访问原生dom节点
    • owner:当前正在构建的Component所属的Component
    • ?typeof:默认为REACT_ELEMENT_TYPE,可以防止XXS
  3. 转化为真实DOM

    虚拟DOM转化为真实DOM的过程大体上可以分为四步: 处理参数批量处理生成html、渲染html

    • 处理参数:当我们处理好组件后,我们需要ReactDOM.render(element, container[, callback])将组件进行渲染,这里会判断是原生标签还是React自定义组件
    • 批量处理:这个过程就会统一进行处理,具体的执行机制,之后会单独写篇文章讲解
    • 生成html:对特殊的DOM标签、props进行处理,并根据对应的标签类型创造对应的DOM节点,利用updateDOMPropertiesprops插入到DOM节点,最后渲染到上面
    • 渲染html:渲染html节点,渲染文本节点,但不同的浏览器可能会做不同的处理

 

6、React更新虚拟DOM(diff算法)

1、准备

   React会维护两个虚拟DOM,通过对比进行更新,最终渲染到真实DOM中。

      diff算法并不是react中提出来的,而是引用并且结合react进行优化,最终形成了react的diff算法。

     举个栗子:

  • 在计算一颗树转化为另一颗树有哪些改变时,传统的diff算法通过循环递归对节点进行依此对比,算法复杂度达到了O(n^ 3),也就是说,如果展示 一千个节点,就要计算十亿次
  • Reactdiff算法,算法复杂度为O(n),如果展示一千个节点,就要计算一千次。可以看出优化成功非常显著

2、react diff算法

      React通过三步走进行优化:

  1. tree diff: DOM 节点跨层级的移动操作特别少,可以忽略不计。所以只进行同级的比较
    React通过updateDepth 对 Virtual DOM 树进行层级控制,也就是同一层,在对比的过程中,如果发现节点不在了,会完全删除不会对其他地方进行比较,这样只需要对树遍历一次就OK了
  2. component diff:拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。相同类型的组件和不同类型的组件
    • 对同种类型组件对比,按照层级比较继续比较虚拟DOM树即可,但有种特殊的情况,当组件A如果变化为组件B的时候,有可能虚拟DOM并没有任何变化,所以用户可以通过shouldComponentUpdate() 来判断是否需要更新,判断是否计算
    • 对于不同组件来说,React会直接判定该组件为dirty component(脏组件),无论结构是否相似,只要判断为脏组件就会直接替换整个组件的所有节点
  3. element diff:对于同一层级的一组子节点,它们可以通过唯一 id 进行区分。

                 1、节点比较,对于同一层级的一子自节点,通过唯一的key进行比较

                2、当所有节点处以同一层级时,React 提供了三种节点操作:插入移动删除

3、循环中的key

  1. 不能使用index: 节点进行插入、移动、删除操作时,索引发生变化,不能正确识别节点
  2. 不能使用index+str: 同上,导致所有节点不能复用
  3. 使用唯一值做key,diff算法的关键点

 

4、fiber

     时间切片,可以将渲染工作进行切片,提高渲染效率。

  • 从运行机制上来解释,fiber是一种流程让出机制,它能让react中的同步渲染进行中断,并将渲染的控制权让回浏览器,从而达到不阻塞浏览器渲染的目的。
  • 从数据角度来解释,fiber能细化成一种数据结构,或者一个执行单元。

Fiber算法的核心概念

  1. ‌任务中断和优先级‌:Fiber算法利用浏览器的空闲时间执行任务,如果遇到更高优先级的任务,当前任务可以被中断,优先执行高级别任务。这种设计允许React在处理复杂界面时更加灵活,不会因为长时间占用主线程而导致页面卡顿。

  2. ‌任务拆分‌:Fiber将任务拆分成一个个的小任务,每个任务都可以独立执行。这种拆分使得任务可以更容易地被中断和重新开始,提高了应用的响应性。

  3. ‌Fiber对象‌:每个Fiber对象包含节点类型、属性、DOM对象、操作标记等信息。Fiber对象之间通过父子关系连接,形成一个树状结构。这种结构使得React可以高效地管理和更新DOM。

Fiber算法的实现细节

  1. ‌构建和提交‌:Fiber算法将DOM比对算法分成两部分:构建(可中断)和提交(不可中断)。构建阶段负责创建和更新Fiber对象,而提交阶段则负责将更新应用到实际的DOM上。

  2. ‌虚拟DOM树的遍历‌:React使用虚拟DOM树来比较前后两次渲染的结果,找出差异并进行更新。Fiber算法通过遍历虚拟DOM树,使用高效的比对算法来减少不必要的DOM操作,从而提高性能。

  3. ‌生命周期方法‌:在Fiber算法中,组件的生命周期方法被分为三个阶段:pre-mutation(变更前)、mutation(变更中)和post-mutation(变更后)。这种划分使得React可以更精细地控制组件的更新过程,进一步提高性能。

通过这些机制,Fiber算法使得React能够更高效地处理复杂的用户界面,提高应用的响应性和性能

   

tips:

          主流的显示器刷新率其实都是60帧/S,也就是一秒画面会高速的刷新60次,按照1S=1000ms,那么一帧的预算时间其实是1000ms/60帧也就是16.66ms

    1. 背景

          React 是函数式编程,单向数据流,需要手动 setState 来更新,所以当数据改变时会默认全部重新渲染整个组件树,而构建虚拟 DOM 采用的同步递归的方式,如果组件很复杂且嵌套深,那么这个构建虚拟 DOM 的过程就需要很多时间,而这种任务默认要执行完才会把控制权交给浏览器,一旦执行时间很长,可能就会地把浏览器卡死。
              fiber 是可以使渲染过程被中断,可以把控制权先交还给浏览器,让位高优先级的任务,等浏览器空闲时再恢复渲染,这样就不会显得卡顿,而是一帧一帧有规律的执行任务,看起来虽然有点慢,但是一直在执行的.
              每一个被创建的虚拟dom都会被包装成一个fiber节点

    2. 特点

      1. 支持增量渲染,fiberreact中的渲染任务拆分到每一帧。(不是一口气全部渲染完,走走停停,有时间就继续渲染,没时间就先暂停)
      2. 支持暂停,终止以及恢复之前的渲染任务。(没渲染时间了就将控制权让回浏览器)
      3. 通过fiber赋予了不同任务的优先级。(让优先级高的运行,比如事件交互响应,页面渲染等,像网络请求之类的往后排)
      4. 支持并发处理(结合第3点理解,面对可变的一堆任务,react始终处理最高优先级,灵活调整处理顺序,保证重要的任务都会在允许的最快时间内响应,而不是完全按顺序来)

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

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

相关文章

Ftrans超大附件插件一键解决难题:outlook邮箱大文件怎么发送?

在日常办公中,通过outlook邮箱发送文件是一种至关重要的沟通和协作工具,具有多方面的作用,并且应用场景广泛。但在实际使用中,也会碰到outlook邮箱大文件怎么发送的难题。可以来了解一下: 一、应用场景 1、内部沟通 日常工作安排:上级领导通过邮件向下属布置工作任务,明…

IDEA-idea2013连接Mysql数据库

IDEA-idea2013连接Mysql数据库 右侧DataBase图表,选择Mysql输入用户名和密码 => 点击TestConnection成功会显示点击这里选择schemas

SpringSecurity5(8-权限注解)

Spring Security 提供多种权限注解,如 @PreAuthorize、@PostAuthorize、@Secured 和 @RolesAllowed,用于方法级别的访问控制。@PreAuthorize 适用于方法执行前权限检查,@PostAuthorize 可在方法执行后验证返回值权限,@Secured 和 @RolesAllowed 主要基于角色控制。注解使用…

Windows Server 2025 中文版、英文版下载 (2025 年 3 月更新)

Windows Server 2025 中文版、英文版下载 (2025 年 3 月更新)Windows Server 2025 中文版、英文版下载 (2025 年 3 月更新) Windows Server 2025 LTSC x64 (updated Mar 2025) 请访问原文链接:https://sysin.org/blog/windows-server-2025/ 查看最新版。原创作品,转载请保留出…

分享报表工具核心三种扩展模型示例

报表工具的核心是父子格扩展模型,通过父子格扩展模型实现各种类型报表,例如网格式报表、行式报表、主子报表、分组报表、交叉报表等。报表有三种扩展模型父子格扩展模型双父格扩展模型兄弟格扩展模型父子格扩展模型B7单元格是第7行所有其它单元格的父格,其它单元格随父格扩展…

centos忘记密码

centos6系统忘记密码: 1、在开机启动的时候快速按键盘上的“E”键 或者“ESC”键,会进入如下界面2、选择你忘记密码的内核,再次按“E”,出现下图,选择第二项,(以kernel开头的行)再次按“E”键3、在信息的最后加“空格”,直接输入数字的“1”(如图)或者 键入“single…

.NET 10 Preview 2 增强了 Blazor 和.NET MAUI

.NET 团队 3.18 发布了.NET 10 Preview 2(https://devblogs.microsoft.com/dotnet/dotnet-10-preview-2/)。.NET 10 Preview 2 主要对 Blazor 和.NET MAUI 进行了增强。Blazor 在 ASP.NET Core 网络开发框架中的组件以及.NET MAUI 获得了最多关注。此次更新主要集中在小的修复…

读DAMA数据管理知识体系指南26数据集成实施指南

读DAMA数据管理知识体系指南26数据集成实施指南1. 工具 1.1. 数据转换引擎/ETL工具1.1.1. 数据转换引擎(或ETL工具)是数据集成工具箱中的主要工具,是每个企业数据集成程序的核心1.1.2. 无论是批量的还是实时的,物理的或虚拟的数据都存在运用非常复杂的工具来开发和执行ETL1…

BFS 算法模板及使用

BFS 算法模板及使用 什么是 BFS 算法? BFS (Breadth-First Search) 算法,中文全称广度优先搜索(宽度优先搜索), 区别于 DFS 算法一条路走到黑的本质, BFS 使用扩散性搜索。它将会根据规则一层一层向下搜索,容易发现,BFS 算法找到的路径一定是最短的,同时,它的时间复…

ResNet-152 模型性能评估

ResNet-152 模型在渴望模式下的性能评估为了预热 GPU,在进行 20 次额外迭代以获取模型的平均推理时间之前,先运行 ResNet-152 模型 10 次。n_warmup = 10n_test = 20dtype = torch.bfloat16inference_time=[]mode=[]t_warmup, _ = timed(lambda:model(input_batch), n_warmup…

推荐专著1《AI芯片开发核心技术详解》、2《智能汽车传感器:原理设计应用》、3《TVM编译器原理与实践》、4《LLVM编译器原理与实践》

4本书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该…

当巴别塔倒下。——从mygo到mujica

。序章 ???? 那时,天下人的口音,言语,都是一样。他们往东边迁移的时候,在示拿地遇见一片平原,就住在那里。他们彼此商量说,来吧,我们要作砖,把砖烧透了。他们就拿砖当石头,又拿石漆当灰泥。他们说,来吧,我们要建造一座城和一座塔,塔顶通天,为要传扬我们的名,…