(虚拟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 过程。

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

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

相关文章

GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程)

&#x1f42f; GitHub教程&#xff1a;最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程) &#x1f4c1; 文章目录 &#x1f42f; GitHub教程&#xff1a;最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图…

0104练习与思考题-算法基础-算法导论第三版

2.3-1 归并示意图 问题&#xff1a;使用图2-4作为模型&#xff0c;说明归并排序再数组 A ( 3 , 41 , 52 , 26 , 38 , 57 , 9 , 49 ) A(3,41,52,26,38,57,9,49) A(3,41,52,26,38,57,9,49)上的操作。图示&#xff1a; tips:&#xff1a;有不少在线算法可视化工具&#xff08;软…

鸿蒙内核源码分析 (内存管理篇) | 虚拟内存全景图是怎样的

初始化整个内存 OsSysMemInitOsMainmain从 main() 跟踪可看内存部分初始化是在 OsSysMemInit() 中完成的。 UINT32 OsSysMemInit(VOID) {STATUS_T ret;OsKSpaceInit();//内核空间初始化ret OsKHeapInit(OS_KHEAP_BLOCK_SIZE);// 内核动态内存初始化 512K if (ret ! LOS_OK…

一款轻量、干净的 Laravel 后台管理框架

系统简介 ModStart 是一个基于 Laravel 的模块化快速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 系统特性 …

第三、四章 if语句 + 循环

第三章 if语句 bool类型 两种&#xff1a;True和False bool_1 True bool_2 False print(f"bool_1变量的内容是&#xff1a;{bool_1}," f"类型是&#xff1a;{type(bool_1)}") print(f"bool_2变量的内容是&#xff1a;{bool_2}," f"类…

解决Selenium元素拖拽不生效Bug

前几天在使用Selenium进行元素拖拽操作时&#xff0c;发现Selenium自带的元素拖拽方法&#xff08;dragAndDrop()&#xff09;不生效&#xff0c;网上的回答也是五花八门&#xff0c;比较混乱&#xff0c;尝试了以下几种方法均无法解决。 方案1&#xff1a;通过dragAndDrop()方…

外部模块介绍(七) 蓝牙HC05

HC05原理图 2. 蓝牙模块的调试 2.1 两种工作模式: HC-05蓝牙串口通讯模块具有两种工作模式:命令响应工作模式和自动连接工作模式。在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。 当模块处于自动连接工作模式时,将自动根据事…

二叉树练习day.3

104.二叉树的最大深度 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root…

pygame旋转直线,计算角色到墙距离

pygame怎么计算距离 在Pygame中&#xff0c;计算两点之间的距离可以使用几何公式。给定两点P1(x1, y1)和P2(x2, y2)&#xff0c;距离D可以用以下公式计算&#xff1a; D √((x2 - x1) (y2 - y1)) 在Python中&#xff0c;你可以使用math库中的sqrt函数来计算平方根。以下是一…

34-5 CSRF漏洞 - CSRF分类

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 1)GET 类型 传参: 参数连接在URL后面 POC构造及执行流程: 构造URL,诱导受害者访问点击利用利用标签进行攻击: 构造虚假URL,在链接上添加payload抓包获取数据包,通过CSRF POC…

excel散点图怎么每个点添加名称

最终效果图&#xff1a; 添加图标元素->数据标签->其他数据标签选项 选择单元格中的值 手动拖动数据标签&#xff0c;调整到合适的位置。

C语言从入门到实战————编译和链接

目录 前言 1. 翻译环境和运行环境 2. 翻译环境 2.1 预处理&#xff08;预编译&#xff09; 2.2 编译 2.2.1 词法分析&#xff1a; 2.2.2 语法分析 2.2.3 语义分析 2.3 汇编 2.4 链接 3. 运行环境 前言 编译和链接是将C语言源代码转换成可执行文件的必经过程&a…

Java面试八股文(更新中)

Java面试八股文 1. 基础篇1.1 Java语言特点1.2 面向对象和面向过程的区别1.3 八种基本数据类型的大小&#xff0c;以及他们的封装类1.4 标识符的命名规则1.5 instanceof 关键字的作用 ************************************************************* 1. 基础篇 1.1 Java语言特…

【Java网络编程】计算机网络基础概念

就目前而言&#xff0c;多数网络编程的系列的文章都在围绕着计算机网络体系进行阐述&#xff0c;但其中太多理论概念&#xff0c;对于大部分开发者而言&#xff0c;用途甚微。因此&#xff0c;在本系列中则会以实际开发者的工作为核心&#xff0c;从Java程序员的角度出发&#…

测试自动化流程设计思路

a) 背景介绍 基于当前互联网敏捷开发的现状&#xff0c;手工人力测试已不足以满足当前快速的版本迭代&#xff1b;以下将介绍一种可实现的自动化设计与使用。 b) 当前版本迭代流程 研发同学从代码库master分支拉出新代码进行研发工作得开发开发完成之后提交到代码库测试同学介入…

ES入门十一:正排索引和倒排索引

索引本质上就是一种加快检索数据的存储结构&#xff0c;就像书本的目录一下。 为了更好的理解正排索引和倒排索引&#xff0c;我们借由一个 **唐诗宋词比赛&#xff0c;**这个比赛一共有两个项目&#xff1a; 给定诗词名称&#xff0c;背诵整首给诗词中几个词语&#xff0c;让…

构建第一个ArkTS用的资源分类与访问

应用开发过程中&#xff0c;经常需要用到颜色、字体、间距、图片等资源&#xff0c;在不同的设备或配置中&#xff0c;这些资源的值可能不同。 应用资源&#xff1a;借助资源文件能力&#xff0c;开发者在应用中自定义资源&#xff0c;自行管理这些资源在不同的设备或配置中的表…

男生穿什么裤子显腿长?男生显腿长裤子分享

现在市面上出现很多劣质而且不耐洗不耐穿的裤子&#xff0c;不但穿着体验感差&#xff0c;而且还可能会对皮肤有影响。为此作为一名穿搭博主&#xff0c;我专门做了这篇关于男生裤子的测评&#xff0c;希望大家能够通过一下的科普知识&#xff0c;对选择裤子有更详细的了解。 什…

CDN加速原理那些事

名词解释 CNAME记录&#xff08;CNAME record&#xff09; CNAME即别名( Canonical Name )&#xff1b;可以用来把一个域名解析到另一个域名&#xff0c;当 DNS 系统在查询 CNAME 左面的名称的时候&#xff0c;都会转向 CNAME 右面的名称再进行查询&#xff0c;一直追踪到最后…

创建型模式--4.抽象工厂模式【弗兰奇一家】

1. 奔向大海 在海贼世界中&#xff0c;位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族&#xff0c;当然了他们的逆向工程做的也很好&#xff0c;会拆船必然会造船。船是海贼们出海所必备的海上交通工具&#xff0c;它由很多的零件组成&#xff0c;从宏观上看…