(虚拟DOM)前端八股文修炼Day10

在这里插入图片描述

一 虚拟 DOM 是什么

虚拟 DOM (Virtual DOM) 本质上是真实 DOM 的一个轻量级的 JavaScript 表示形式。它是一个在内存中的抽象,用于描述真实 DOM 的结构和内容。虚拟 DOM 提供了一种机制,允许开发者通过操作 JavaScript 对象来间接更新页面,而不是直接操作更加繁重和耗费性能的真实 DOM 元素。

虚拟 DOM 的核心组成:

  • 节点对象: 虚拟 DOM 树中的每个节点对应于真实 DOM 树中的一个节点。这些节点对象可能代表 HTML 元素、文本内容或者是组件。

  • 属性和子节点: 虚拟 DOM 节点存储了对应真实 DOM 节点的属性(如 id、class、style 等)和子节点信息,以确保可以准确地映射到真实的 DOM 结构。

虚拟 DOM 的工作方式:

  1. 初始化渲染: 应用首次加载时,根据应用的初始状态,构建一棵完整的虚拟 DOM 树。

  2. 状态更新: 当应用状态发生变化时(例如,用户输入或从后端获取数据),框架会创建一个新的虚拟 DOM 树,这个树反映了最新的应用状态。

  3. 差异比较(Diffing): 框架比较新旧虚拟 DOM 树之间的差异。这个过程被称为 Diffing,它识别出实际需要在真实 DOM 中更新的部分。

  4. 批量更新(Patching): 根据差异比较的结果,框架计算出最高效的方式来更新真实 DOM。这一步骤确保只对真实 DOM 中实际改变的部分进行操作,从而最大限度减少性能消耗。

虚拟 DOM 的优点:

  • 性能提升: 通过减少直接操作真实 DOM 的次数,虚拟 DOM 机制显著提高了网页的响应速度和性能。

  • 跨平台: 虚拟 DOM 不依赖于浏览器 API,使其容易被移植到其他平台,如 React Native 使用虚拟 DOM 来构建原生应用。

  • 易于理解和维护的 UI 逻辑: 开发者可以专注于数据的状态和应用逻辑,而不必担心具体的 DOM 操作细节。这使得代码更加易于理解和维护。

虚拟 DOM 是现代前端框架中用于提高应用性能和开发效率的关键技术之一。

二 React diff 算法的原理是什么

React 的 Diff 算法是 React 虚拟 DOM 技术中的核心机制,它用于高效地对比前后两次虚拟 DOM 树的差异,并将这些差异应用到真实的 DOM 上,以实现快速的 UI 更新。React 的 Diff 算法基于两个主要假设:

  1. 两个不同类型的元素会产生不同的树。 当根节点类型不同时,React 会拆卸原有的树并建立新树。例如,一个<div>元素变成了<span>,或者一个组件变成了另一个不同的组件,React 将会销毁旧的树并完整地构建新树。

  2. 通过开发者指定的 key 属性,可以在不同的渲染中保持元素的稳定性。 在处理动态子元素集合时,开发者应该给每个列表项分配一个唯一的 key 属性,这样 React 可以重新使用和重新排序现有的子元素,而不是重新创建它们。

React Diff 算法的工作原理细分为三个层次:

1. 树的层级对比:
  • React 首先对比两棵树的根节点。
  • 如果根节点的类型不同,React 会销毁旧树,并从头开始构建新树。
  • 如果根节点的类型相同,React 会保留根节点,并递归地对比并更新其子节点。
2. 组件的对比:
  • 当对比两个相同类型的 React 组件时,React 会保留 DOM 节点,仅对比并更新变化的属性。
  • 对于组件实例,React 会更新组件的 props,并重新调用 render 方法来决定如何更新。这个过程可能会导致组件的状态变化。
3. 子节点的对比:
  • 当处理同一层级的子节点时,React 会尽可能地重用节点。
  • 使用 key 属性可以帮助 React 确定哪些子元素可以保持不变,哪些需要重新排列或创建。

优化:

React 的 Diff 算法还采用了一些优化策略,如只进行同级别(不跨层级)的对比,这大大减少了对比的复杂度和时间。尽管这可能导致在某些极端情况下的非最优更新路径,但在实践中这种情况很少发生,并且得到的性能提升远远超过了这种潜在的不足。

总的来说,React 的 Diff 算法通过智能的对比策略和假设,减少了不必要的 DOM 更新,从而提高了应用的性能和响应速度。

三 React key

React 中的 key 属性在组件和元素的列表渲染中扮演着至关重要的角色。它的主要目的是帮助 React 识别哪些项发生了变化、添加或者被移除。简而言之,key 提供了元素的唯一标识。

作用和重要性:

  1. 性能优化: 在对比虚拟 DOM 时,key 帮助 React 识别元素是否变更,这使得 React 可以仅更新实际改变了的元素,而不是删除旧的 DOM 元素并创建新的。这种机制极大地提高了应用的性能。

  2. 减少重复渲染: 通过确保每个元素有一个唯一的 key,React 可以避免在数组中重新渲染所有元素。假设你有一个项目列表,只更新了一个项目的内容,如果每个项目都有独一无二的 key,React 将只重新渲染那个被更新的项目,而不是整个列表。

  3. 正确的元素状态管理: 在使用列表和其他可变数据结构时,如果没有 key,React 可能会错误地复用组件状态。这可能会导致难以追踪的错误和不一致的 UI 状态。使用 key 可以保证即使数据项的位置改变,元素状态也能正确地被管理和复用。

使用方法:

在渲染列表时,你应该给每个被渲染的列表项一个唯一的 key 属性:

const todos = [{id: 1, text: 'Do homework'}, {id: 2, text: 'Read book'}];

function TodoList() {
  return (
    <ul>
      {todos.map(todo =>
        <li key={todo.id}>
          {todo.text}
        </li>
      )}
    </ul>
  );
}

在这个例子中,每个 todo 项有一个唯一的 id,这个 id 被用作 key。这样,即使数据变动引起顺序改变,React 也能准确地识别和处理每一个 todo 项,保持高效的渲染性能和正确的组件状态。

注意: 使用数组索引作为 key 是最后的选择,因为如果项目顺序发生变化,索引也会变,这可能导致性能问题或者状态错误。尽可能地使用一个能够唯一标识元素的属性作为 key

key解决的问题

在React等使用虚拟DOM的前端框架中,key 属性主要解决的是识别和追踪列表中各个元素在重新渲染过程中的变化问题。具体来说,key 属性在以下方面发挥着重要作用:

  1. 性能优化: 当组件状态发生变化时,React会重新渲染组件。如果组件渲染的是一个列表,React需要决定哪些列表项被更新、添加或删除。key 帮助React识别列表中每个元素的身份,以便它可以只重新渲染必要的元素,而不是整个列表。这大大提高了应用程序的性能。

  2. 减少渲染时间: 如果没有key,React在更新列表时可能会采取更消极的策略,比如重新渲染整个列表,从而导致不必要的DOM操作,这会降低应用性能。

  3. 维护组件状态: 在动态的列表中,如果列表项的顺序可以改变,没有key或者使用错误的key(如数组索引)可能会导致状态管理问题。例如,如果列表项被重新排序,React可能会错误地将某个组件的状态与另一个组件关联起来。正确的key可以确保组件状态与正确的元素相关联,即使元素的顺序发生了改变。

  4. 识别元素的增加和删除: 在列表操作中,当添加或删除元素时,key可以帮助React快速识别哪些元素是新增的,哪些是被删除的,从而进行针对性的DOM操作,而不是重新渲染整个列表。

总结来说,key的主要作用是提高性能,通过为列表中的每个元素分配一个稳定且独特的标识符,帮助React高效地执行虚拟DOM的diff算法,只更新变化的部分,维护状态的一致性,并减少不必要的DOM操作。因此,在开发过程中,为列表中的每个元素提供唯一的key值是一种最佳实践。

四 虚拟 DOM 的引入与直接操作原生 DOM 相比,哪一个效率更高为什么

虚拟 DOM 的引入通常被认为在大多数现代 Web 应用场景中比直接操作原生 DOM 拥有更高的效率,主要原因包括以下几点:

1. 批量DOM操作和最小化DOM更新

虚拟 DOM 通过在内存中对比前后状态的差异(通过所谓的 diff 算法),来确定真实 DOM 需要进行的最小更新。然后,这些变化会被批量地、一次性应用到真实 DOM 上。这种方法减少了浏览器的重绘(repaint)和重排(reflow)操作,这些操作是影响 Web 应用性能的主要因素。

2. 减少直接DOM操作的开销

直接操作 DOM 是昂贵的,因为每次更改都会直接影响到浏览器的文档对象模型(DOM),这可能会引发一系列的重绘和重排。相比之下,虚拟 DOM 的操作是在 JavaScript 内存中进行的,与直接操作真实 DOM 相比,它能显著减少这种开销。

3. 提高开发效率和可维护性

虚拟 DOM 除了性能优势之外,还通过声明式编程模型来简化了开发过程。开发者可以关注于状态(state)的管理,而不是如何操作 DOM 来反映这些状态的变化。这使得代码更容易理解和维护,并且能够提高开发效率。

但是,也有例外情形

需要注意的是,虚拟 DOM 并非在所有情况下都比直接操作原生 DOM 更高效。例如,在处理极其简单的 DOM 更新时,原生 DOM 操作可能会更快,因为此时虚拟 DOM 的 diff 算法和更新策略所带来的开销可能会超过直接操作原生 DOM 的成本。然而,随着应用规模的增长和复杂度的提升,虚拟 DOM 的优势会变得更加明显。

结论

总的来说,虚拟 DOM 的引入主要是为了提高大规模应用的性能和开发效率。通过批量更新和最小化真实 DOM 操作,它能够提供比直接操作原生 DOM 更好的性能优势,特别是在处理大型或复杂的应用时。然而,对于极其简单的场景,直接操作 DOM 可能会稍微快一些。选择合适的方法取决于具体的应用场景和性能要求。

五 为什么React 与 Vue 的 diff 算法有何不同

React 和 Vue 都使用虚拟 DOM 以及 diff 算法来高效地更新 DOM,但它们在具体实现上有些差异。以下是 React 和 Vue 在 diff 算法上的一些主要区别:

React 的 Diff 算法:

  • 层级对比: React 对虚拟 DOM 树进行层级对比,如果一个组件的类型发生了变化,React 会销毁整个组件下的子树并重新创建。
  • 列表对比: 在对比列表元素时,如果没有明确的key,React 默认采用索引作为每项的 key 值,这可能会导致性能问题和组件状态的错误关联。提供一个独一无二的key可以帮助React更准确、更快地识别元素。
  • 子元素对比: React 默认情况下会逐个对子元素进行对比,这就需要开发者理解并合理使用key以优化性能。

Vue 的 Diff 算法:

  • 双端比较: Vue 的 diff 算法更为复杂。它采用了一种双端比较的策略。当对列表进行对比时,Vue 同时从列表的两端(头部和尾部)开始进行元素的对比,这样可以在一些情况下减少元素的移动次数。
  • 就地更新: 如果没有提供key,Vue 将尽可能就地复用同类型的元素,而不是销毁再重新创建,尽管这样可能会导致一些边缘情况下的问题。
  • 列表对比优化: Vue 在处理列表时进行了一些针对性优化,比如在处理含有相同子元素的静态节点列表时,可以提供更高效的更新。

总的来说,Vue 的 diff 算法在处理列表对比时进行了更多的优化,特别是通过双端对比算法减少不必要的元素移动。然而,不管是 React 或 Vue,合理使用key属性都是至关重要的,因为它们都依赖于key来识别列表中各个元素的身份,以执行高效的更新。开发者应当根据具体情况,为列表中的每个元素提供一个稳定且独一无二的key值,以帮助框架准确快速地进行虚拟 DOM 的 diff 过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Clip论文学习

学习过程如上 学习时&#xff0c;图片与文本对应&#xff08;句子&#xff09;&#xff0c;共有n个句子与n个文本&#xff0c;进行对比学习 测试时&#xff0c;将标签句子化&#xff0c;再将其放入encoder中操作。最后找出特征最相似的。 特点&#xff1a;泛化能力强&#x…

点击上传文件

一、页面样式&#xff1a; &#xff08;1&#xff09;点击前&#xff1a; &#xff08;2&#xff09;点击后&#xff1a; 设计&#xff1a;①自定义elementPlus图标&#xff1b;②使用Tooltip实现鼠标悬浮按钮上出现文字提示&#xff1b;③上传与更换的切换样式&#xff1b;…

蓝桥备赛——素数

素数定义 试除法判断 from math import * def if_prime(n):if n==1:return Falsem=int(sqrt(n)+1)for i in range(2,m): #范围是2到根下n+1if n%i==0:return Falsereturn True print(if_prime(5)) 试除法判断素数。就是判断是否除了1和本身还有其他可以整除自己的数,…

模块十三 异常_Object

回顾与重点 模块十二回顾 权限修饰符&#xff1a; public → protected → 默认 → private a. 构造一般用public&#xff1a;便于new对象 b. 成员方法一般用public&#xff1a;便于调用 c. 属性一般用private&#xff1a;封装思想 final&#xff1a;最终的 a. 修饰类&#x…

如何从iPhone恢复已删除的照片

这些照片是我们今天生活中最珍贵的回忆。它们捕捉了我们一生珍惜的时刻。但是&#xff0c;丢失这些记忆可能是毁灭性的&#xff0c;尤其是在不小心从iPhone中删除它们时。 幸运的是&#xff0c;有一些方法可以从iPhone恢复已删除的照片。在这篇博文中&#xff0c;我们将讨论从…

【opencv】示例-detect_mser.cpp 使用 MSER 算法来检测图像中的极值区域

#include <opencv2/core.hpp> // 包含OpenCV核心操作的头文件 #include <opencv2/imgproc.hpp> // 包含图像处理功能的头文件 #include <opencv2/highgui.hpp> // 包含图形用户界面的头文件 #include <opencv2/features2d.hpp> // 包含特征检测相关功能…

【数据结构】考研真题攻克与重点知识点剖析 - 第 5 篇:树与二叉树

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

C# + OpencvSharp4 错误信息收集

异常1&#xff1a; 初次使用&#xff0c;如下代码报错&#xff0c;OpenCvSharp.OpenCvSharpException:“imread failed.” Mat src Cv2.ImRead("Source.png", ImreadModes.Unchanged); 原因&#xff1a;检查Nuget包与OpencvSharp4库相关安装是否完整&#xff0c;…

虚拟地址的设置与应用全攻略

在计算机网络和操作系统中&#xff0c;虚拟地址是一个核心概念&#xff0c;它允许程序在逻辑上拥有连续的内存空间&#xff0c;而无需关心实际的物理内存布局。虚拟地址的引入极大地简化了程序的开发和内存管理&#xff0c;提高了系统的灵活性和安全性。虎观代理将详细解析虚拟…

Spring Boot中整合JodConverter实现文件在线预览

Spring Boot中整合JodConverter实现文件在线预览 1.安装LibreOffice 24.2 下载地址 LibreOffice 是一款功能强大的办公软件&#xff0c;默认使用开放文档格式 (OpenDocument Format , ODF), 并支持 *.docx, *.xlsx, *.pptx 等其他格式。 它包含了 Writer, Calc, Impress, Dra…

java基于微服务的智慧工地管理云平台SaaS源码 数据大屏端 APP移动端

目录 智慧工地云平台概述 智慧工地功能 &#xff08;项目端&#xff09; 一、劳务管理&#xff1a; 二、施工安全管理&#xff1a; 三、视频监控管理&#xff1a; 四、机械安全管理&#xff1a; 五、施工质量管理&#xff1a; 六、绿色文明施工&#xff1a; 七、施工综…

CSS3如何实现雷达扫描图(动态样式)

动态样式控制雷达扫描和暂停&#xff1a; //html部分&#xff1a; <view class"radar" :style"{--state:animationPlayState}"></view>data部分&#xff1a; animationPlayState: paused, methods: changeStatus(){this.animationPlayState …

Failed to start docker.service: Unit is not loaded properly: Invalid argument.

Failed to start docker.service: Unit is not loaded properly: Invalid argument. 未知原因&#xff1a;docker服务无法正常load 解决方式&#xff1a; 卸载docker&#xff0c; 删除docker.service 重新安装docker Docker是一种相对使用较简单的容器&#xff0c;我们可以通过…

证书生成和获取阿里云备案获取密钥流程

1.在java文件夹下 输入 cmd 打开命令行窗口 2. keytool -genkey -alias 证书名 -keyalg RSA -keysize 2048 -validity 36500 -keystore 证书名.keystore 输入这一行&#xff0c;把证书名三个字 改成 项目的名称&#xff08;例如&#xff1a;D23102802&#xff09; 3. 密码默认填…

【会议】Oracle自动化运维峰会

2023年7月21日&#xff0c;杭州。我组织了Oracle自动化运维峰会&#xff0c;大约有20人左右参加会议。以下是会议主题&#xff1a; Oracle自动化运维能力是Oracle 19c自动化运维体系中非常重要的一环&#xff0c;自动化索引、自动化SQL优化、资源隔离等技术能够非常好的提升运维…

备考ICA----Istio实验17---TCP流量授权

备考ICA----Istio实验17—TCP流量授权 1. 环境准备 1.1 环境部署 kubectl apply -f <(istioctl kube-inject -f istio/samples/tcp-echo/tcp-echo.yaml) -n kim kubectl apply -f <(istioctl kube-inject -f istio/samples/sleep/sleep.yaml) -n kim1.2 测试环境 检测…

使用Python将多张图片转换为动态GIF图像

在本文中&#xff0c;我们将学习如何使用Python编写代码&#xff0c;将多张静态图片转换为一个动态的GIF图像。无论你的图片格式是JPEG&#xff08;.jpg&#xff09;还是PNG&#xff08;.png&#xff09;&#xff0c;我们都将使用Python中的PIL库来实现这一功能。通过本文的学习…

k8s_入门_命令详解

命令详解 kubectl是官方的CLI命令行工具&#xff0c;用于与 apiserver进行通信&#xff0c;将用户在命令行输入的命令&#xff0c;组织并转化为 apiserver能识别的信息&#xff0c;进而实现管理k8s各种资源的一种有效途径 1. 帮助 2. 查看版本信息 3. 查看资源对象等 查看No…

精品PPT-数据治理总体解决方案新版(免费下载)

1、知识星球下载&#xff1a; 如需下载完整PPTX可编辑源文件&#xff0c;请前往星球获取&#xff1a;https://t.zsxq.com/19F4dDDrv 2、免费领取步骤&#xff1a; 【1】关注公众号 方案驿站 【2】私信发送 数据治理新版 【3】获取本方案PDF下载链接&#xff0c;直接下载即可…

【C++】手搓 list 容器

送给大家一句话&#xff1a; 若结局非你所愿&#xff0c;就在尘埃落定前奋力一搏。—— 《夏目友人帐》 手搓 list 容器 1 前言1.1 底层结构1.2 使用场景1.3 功能简介 2 框架搭建2.1 节点类2.2 list 类2.3 迭代器类 3 功能实现3.1 begin() 与 end()3.2 插入操作3.3 删除操作3…