详谈面试题:Vue、React为什么使用虚拟DOM

server/2024/11/29 21:09:38/

虚拟DOM是一种在前端框架中广泛使用的技术,它可以提升开发效率。那么国外流行的框架svelte没有使用虚拟DOM,而是直接操作真实DOM,效率依然很高。为什么Vue和React不采用这种方式呢?

目录

一、框架设计

二、解耦运行环境 

三、总结


一、框架设计

Vue和React的框架设计无法做到这点,因为框架的颗粒度没有那么细,它们的最小颗粒度是精确到组件的,也就是说,在Vue和React的框架中,数据变化了,操作的不是真实DOM,而是组件。

组件中是由render函数来渲染组件的,假如组件中有很多真实DOM,如果数据变化,会导致render函数重新运行,在react里面就是函数式组件重新运行,数据变化后在render函数重新生成真实DOM的代价太大了,因为可能操作到的数据,只关联一个真实的DOM,而重新运行把很多不需要的的DOM生成出来了。效率就会非常低。因此选择生成虚拟DOM(JS对象),通过对比,精准定位到真实DOM哪里需要更新。

而Svelte不需要考虑这样的问题。

Svelte框架选择不使用虚拟DOM而是直接操作真实DOM,并且依然保持高效率的原因主要有以下几点:

  1. 编译时优化:Svelte通过其强大的编译器在构建时将模板和响应式逻辑转换成高效的JavaScript代码。这意味着所有对DOM的操作都在编译时被优化,而不是在运行时。

  2. 声明式编程:Svelte允许开发者以声明式的方式编写代码,框架自动处理DOM更新。开发者只需关注状态变化,而框架负责将这些变化映射到DOM上,减少了手动操作DOM的复杂性。

  3. 避免不必要的DOM操作:Svelte的编译器能够精确地识别出哪些DOM操作是必要的,从而避免不必要的DOM操作和渲染,这减少了运行时的性能开销。

  4. 响应式声明:在Svelte中,开发者只需声明响应式变量,框架会自动处理依赖跟踪和更新DOM,这种机制减少了手动操作DOM的需要,并且提高了效率。

二、解耦运行环境 

Vue和React的框架在设计时,是希望代码可移植到其他环境,如小程序,移动端等等,而不仅仅是浏览器环境。所以不能绑定真实DOM,因为真实DOM只有浏览器环境中有。

为了解耦环境,将真实DOM提取成JS对象的形式来描述界面,JS对象是ES的范畴,只要环境支持ES,就一定支持ES对象。这样不同环境都可以使用同一套对象描述界面,用虚拟DOM进行不同的渲染。支持多端开发

三、总结

  1. 性能优化:虚拟DOM通过减少对真实DOM的操作次数来提高性能。由于DOM操作是昂贵的,直接操作DOM会导致性能问题,尤其是在数据频繁更新时。虚拟DOM允许框架通过比较前后两个虚拟DOM树的差异,找出最小更新范围,然后只更新那些实际变化的部分,从而减少不必要的DOM操作。

  2. 跨平台渲染:虚拟DOM提供了跨平台渲染的能力,使得Vue和React的应用不仅限于浏览器环境。例如,React Native利用虚拟DOM在移动设备上渲染应用界面,而Vue也可以通过Weex等技术实现跨平台渲染。

  3. 批量更新和优化:虚拟DOM允许批量更新,将多个数据变更合并为一次操作,减少DOM操作次数,提高性能。这种批量更新机制可以减少页面的重绘和回流,提升渲染效率。

  4. 开发体验:虚拟DOM提供了声明式的编程模式,开发者可以更专注于数据和状态,而不必过多关心底层的DOM操作。这种模式简化了开发流程,提高了开发效率。

  5. 组件粒度的更新:在Vue和React中,数据变化时,操作的不是单个真实DOM,而是组件。组件的更新是由render函数来渲染的,如果组件中包含很多真实DOM,数据变化会导致render函数重新运行,这可能导致不必要的DOM生成,影响效率。虚拟DOM通过对比,精准定位到真实DOM哪里需要更新,避免了这种低效的操作。

  6. 避免回流和重绘:虚拟DOM不会进行回流和重绘;真实DOM在频繁操作时引发的回流重绘导致性能降低。虚拟DOM有效降低大面积的重绘与排版,因为是和真实DOM对比,更新差异部分,所以只渲染局部。


http://www.ppmy.cn/server/145993.html

相关文章

GPU 选型指南

根据 GPU 架构的不同,可分为以下几类: NVIDIA Volta 架构 代表型号: V100 配备第二代 Tensor Core,是较早支持深度学习的 GPU,仍适用于部分训练任务。性能特点:相比后续架构,V100 的训练性能…

【es6】原生js在页面上画矩形添加选中状态高亮及显示调整大小控制框(三)

接上篇文章,这篇实现下选中当前元素显示调整大小的控制框,点击document取消元素的选中高亮状态效果。 实现效果 代码逻辑 动态生成控制按钮矩形,并设置响应的css // 动态添加一个调整位置的按钮addScaleBtn(target) {const w target.offsetWidth;con…

Flutter:encrypt插件 AES加密处理

1、pubspec.yaml导入插件 cupertino_icons: ^1.0.8 # 密码加密 encrypt: 5.0.3encrypt封装 import package:encrypt/encrypt.dart; /// 加密类 class EncryptUtil {static final EncryptUtil _instance EncryptUtil._internal();factory EncryptUtil() > _instance;Encrypt…

C#身份证识别接口集成、身份证文字信息提取、身份证信息录入

身份证识别接口为什么会受到互联网平台的青睐?传统的身份验证方式往往需要用户手动输入个人信息,这不仅耗时耗力,还容易出现误操作影响身份认证结果的现象。翔云身份证识别接口通过先进的OCR(光学字符识别)技术&#x…

使用 Python 的 pdfplumber 库高效解析 PDF 文件

使用 Python 的 pdfplumber 库高效解析 PDF 文件 PDF 文件是日常办公和数据处理中常见的文件格式,而 pdfplumber 是一个专为 PDF 文件解析设计的 Python 库,可以轻松提取文本、表格、图像等内容。本文将介绍 pdfplumber 的基本功能、使用方法&#xff0…

Rust如何编制前端路由

目的:根据前端build文件夹下的目录结构,生成路由,将前端html文件返回。 /// 设置 HTML 文件路由 pub fn route(cfg: &mut web::ServiceConfig) {if Path::new("client/build/index.html").exists() {let index_content match…

阅读《基于蒙特卡洛法的破片打击无人机易损性分析》_笔记

目录 基本信息 1 引言 1.1 主要研究内容 1.2 研究必要性(为什么要研究) 1.3 该领域研究现状(别人做了什么/怎么做的) 2 主要研究过程(我们做了什么) 2.1 建立目标仿真模型 2.2 确定毁伤依据 2.3 无…

Android.mk里如何指定编译模块的输出路径

在 Android.mk 文件中,LOCAL_MODULE_PATH_32、LOCAL_MODULE_PATH_64 和 LOCAL_MODULE_RELATIVE_PATH 可以一起使用,以灵活地控制不同架构模块的安装路径。下面是一个详细的示例,展示如何结合使用这些变量。 示例项目结构 假设你的项目结构如…