【React】02-如何理解React通过对DOM的模拟,最大限度地减少与DOM的交互

如何理解React通过对DOM的模拟,最大限度地减少与DOM的交互

  • 背景
  • 分析
  • 关于虚拟DOM

背景

在学习React的过程中,发现很多文档上关于React的高效都有这么一句话的描述——React通过对DOM的模拟,最大限度地减少与DOM的交互,对于我这种前端小白来说,理解起来还是挺费劲的,所以找了些文档学习了一番。

分析

在查找资料的过程中,笔者发现关于这句话的描述其实包含着下面的知识点:

  • 虚拟DOM: React引入了虚拟DOM的概念。虚拟DOM是一个存在于内存中的树形结构,它对应着实际的DOM树。在React中,组件的状态变化会首先在虚拟DOM上进行操作,而不是直接操作实际的DOM。

关于虚拟DOM

这里我们先以一个计数器为例子,分别看看React和JavaScript对它的实现方式:
React实现方式

  1. 封装Counter.js
import React from "react";


// 计数器组件
const Counter = ({ count, onIncrement }) => (
  <div>
    <p>Count: {count}</p>
    <button onClick={onIncrement}>Increment</button>
  </div>
);

export default Counter;
  1. 在App.js中引入组件
function App() {
/**计数器组件 */
  const [count, setCount] = useState(0);

  // 处理递增事件
  const handleIncrement = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <h1>Counter App</h1>
      <Counter count={count} onIncrement={handleIncrement} />
    </div>
  );
}

export default App;

JavaScript实现方式:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Counter App</title>
  </head>
  <body>

    <div id="counterContainer">
      <p id="countDisplay">Count: 0</p>
      <button id="incrementButton">Increment</button>
    </div>

    <script>
      // 获取DOM元素
      var countDisplay = document.getElementById('countDisplay');
      var incrementButton = document.getElementById('incrementButton');

      // 初始化计数器
      var count = 0;

      // 处理按钮点击事件
      function handleIncrement() {
        count++;
        countDisplay.textContent = 'Count: ' + count;
      }

      // 添加按钮点击事件监听器
      incrementButton.addEventListener('click', handleIncrement);
    </script>

  </body>
</html>

对比上面两种实现方式,JavaScript 直接对实际DOM进行操作,需要我们手动管理状态和UI之间的同步,每次计数+1时,同步修改UI展示。随着项目越来越大,当我们直接修改的DOM改动的频次越多,甚至涉及位置变换,那么就可能带来重排和重绘的问题了**。**

  1. 重排: 当改变影响到页面布局的属性时,例如修改了元素的尺寸、位置、添加或删除了DOM元素等,浏览器可能会触发重排。重排是一项比较昂贵的操作,因为它涉及到重新计算元素的几何属性和页面的布局,可能导致整个页面的重新渲染。
  2. 重绘: 当改变影响到元素的样式(但不涉及布局的改变)时,例如修改了颜色、背景等,浏览器可能会触发重绘。重绘相对于重排来说开销较小,因为它只涉及到重新绘制元素的外观。

再来看看React的实现方式,首先我们可以知道所有的HTML的DOM节点都可以用JS方式去表示,而React在这里巧妙的利用JS 表示 DOM对象的方式,避免了对DOM的直接操作,类似于中间加了一层缓存操作。(这里又想到一句话,计算机领域大部分问题都可以通过中间加一层解决)。如图所示,通过react-developer-tools工具,我们可以更加直观看到React如何表示我们的HTML的DOM结构。

image.png
React这种在内存中,采用JS 表示 DOM对象的方式,又有一个更加专业点的名称虚拟DOM。它通过采用虚拟DOM差异算法来最小化对实际DOM的直接操作。

以上面计时器为例,React在渲染过程中,会首先根据render的结果将这个树状结构在JS里创建出来,这个树状结构就是虚拟DOM层,当我们的计数器发生变化时,React会将这个新的虚拟DOM和正在呈现的虚拟DOM进行对比,并找出其中的差异,然后用最少的DOM操作完成这个更新

再回到我们的标题**如何理解React通过对DOM的模拟,最大限度地减少与DOM的交互?**这里我们可以做一下小结了,React通过引入虚拟DOM,当DOM发生修改时,在内存中进行差异对比,最大限度地的用最少的DOM操作完成这些操作。

随着深入了解,除去DOM,关于这句话的理解,其实也还包含了如下几个知识点,这里先列举出来:

  1. 批处理: React会将一系列对虚拟DOM的操作合并成一个批处理。这样可以减少实际DOM操作的次数,从而提高性能。React通过一些策略,例如合并相邻的setState调用,来优化实际DOM的更新。
  2. 差异算法(Reconciliation): 在组件状态发生变化时,React会通过比较新旧虚拟DOM树的差异,找出最小的更新操作。然后,只对实际需要更新的部分进行DOM操作。这就是所谓的“协调”(Reconciliation)过程。
  3. DOM更新的延迟执行: React会尽量将DOM更新的执行时机延迟到最合适的时候。例如,在浏览器的空闲时期,或者通过使用 requestAnimationFrame 等API来调度更新,以确保更新不会影响用户的交互体验。

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

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

相关文章

Springboot集成RabbitMq一

0、知识点 1、创建项目-生产者 默认官方start.spring.io已不支持自动生成低版本jkd的Spring项目&#xff0c;自定义用阿里云的starter即可&#xff1a;https://start.aliyun.com 2、创建配置类 package com.wym.rabbitmqprovider.utils;import org.springframework.amqp.core.…

Vue3-34-路由-路由配置参数 props

说明 路由的路径中可以携带参数&#xff0c; 形式如 &#xff1a;/a/:pname &#xff0c;这个:表示这是个参数&#xff0c;pname &#xff1a;表示 参数名称。 在组件中&#xff0c;可以通过 当前路由对象的 params 属性来获取到这个参数&#xff0c; 当前路由对象 可以通过 us…

[Ray Tracing: The Rest of Your Life] 笔记

前言 开年第一篇博客~ 整理了三四个小时才整理完orz。 这一部分是光线追踪三部曲的最后一部&#xff0c;主要介绍了蒙特卡洛积分、重要性采样等内容。场景上没有什么大的改变&#xff0c;基本上就是在Cornell Box中渲染的&#xff0c;本篇主要在加速收敛&#xff0c;提升渲染效…

踩坑记录-安装nuxt3报错:Error: Failed to download template from registry: fetch failed;

报错复现 安装nuxt3报错&#xff1a;Error: Failed to download template from registry: fetch failednpx nuxi init nuxt-demo 初始化nuxt 项目 报错 Error: Failed to download template from registry: fetch faile 解决方法 配置hosts Mac电脑&#xff1a;/etc/hostswin电…

java StringBuilder对比String的优点和15个经典案例

文章目录 区别&#xff1a;1. 字符串拼接2. 构建动态查询语句3. 格式化输出4. 字符串反转5. 插入字符串6. 删除子串7. 字符串替换8. 构建复杂JSON或XML结构9. 处理用户输入的大量数据10. 动态生成HTML页面11. 处理字符串格式转换12. 实现字符串缓冲区13. 拼接大量字符串数组元素…

LLVM(简介)

历史 LLVM(low level virtual machine)起源于伊利诺伊大学的一个编译器实验项目&#xff0c;目前已经发展成一个集编译器和工具链为一体的商业开源项目&#xff0c;因此其英文名称的含义被扩大&#xff0c;不再仅仅是字面意思。其创始人为 Chris Lattner。LLVM项目遵循的开源许…

java数据结构与算法刷题-----LeetCode746. 使用最小花费爬楼梯

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

嵌入式系统(二)单片机基础 | 单片机特点 内部结构 最小系统 电源 晶振 复位

上一篇文章我们介绍了嵌入式系统 嵌入式系统&#xff08;Embedded System&#xff09;是一种特定用途的计算机系统&#xff0c;它通常嵌入在更大的产品或系统中&#xff0c;用于控制、监测或执行特定的任务。这些系统通常由硬件和软件组成&#xff0c;旨在满足特定的需求&…

SQL窗口函数大小详解

窗口大小 OVER 子句中的 frame_clause 选项用于指定一个滑动的窗口。窗口总是位于分区范围之内&#xff0c;是分区的一个子集。指定了窗口之后&#xff0c;分析函数不再基于分区进行计算&#xff0c;而是基于窗口内的数据进行计算。 指定窗口大小的语法如下&#xff1a; ROWS…

了解并使用django-rest-framework-jwt

一 JWT认证 在用户注册或登录后&#xff0c;我们想记录用户的登录状态&#xff0c;或者为用户创建身份认证的凭证。我们不再使用Session认证机制&#xff0c;而使用Json Web Token&#xff08;本质就是token&#xff09;认证机制。 Json web token (JWT), 是为了在网络应用环…

2023年12月GESP C++七级编程题转Python真题解析

七、2023年12月GESP C(Python)七级编程题 2023年12月GESP Python最高六级&#xff0c;但C与Python同级编程题相同。本篇引用2023年12月GESPC七级编程题&#xff0c;用Python实现。 【七级编程题1】 【试题名称】&#xff1a;商品交易 时间限制&#xff1a;1.0 s 内存限制&…

CMake入门教程【核心篇】引用子模块.cmake文件(include)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 include子模块举个例…

四、HTML 属性

属性是 HTML 元素提供的附加信息。 一、HTML 属性 HTML 元素可以设置属性属性可以在元素中添加附加信息属性一般描述于开始标签属性总是以名称/值对的形式出现&#xff0c;比如&#xff1a;name"value"。 二、 属性实例 HTML 链接由 <a> 标签定义。链接的地…

HC-05蓝牙模块--------手机与STM32通信(代码编写)(上位机配置)保姆级教程

⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩因为之前无论是电赛还是做项目&#xff0c;都用到了蓝牙模块&#xff0c;如&#xff1a;手机和stm32的通信&#xff0c;电赛中的双车通信&#xff0c;还是遥感小车的…

教育机构培训系统小程序功能清单

制作一款适合自己的教育机构培训系统小程序&#xff0c;可以为学员提供更便捷的学习体验&#xff0c;同时提高机构的教学效率。今天将详细介绍如何使用乔拓云平台制作教育机构培训系统小程序。 在浏览器搜索乔拓云&#xff0c;登录到后台&#xff0c;选择教育系统并点击进入。在…

使用MQTT.JS创建一个网页版的MQTT客户端

一、MQTT.JS介绍 MQTT.js 是一个开源的 MQTT 协议的客户端库&#xff0c;使用 JavaScript 编写&#xff0c;主要用于 Node.js 和 浏览器环境中。是JavaScript 环境下的 MQTT 客户端库。可以用于微信小程序、支付宝小程序等定制浏览器环境。 我们可以直接在HTML文件中进行调用…

静态代理、JDK动态代理、CGLIB动态代理以及JDK和CGLIB动态代理的区别

代理 什么是代理&#xff1f;两个设计原则三要素 静态代理静态代理的实现定义接口-定义行为静态代理 -> 目标角色静态代理-> 代理角色静态代理测试 特点 JDK动态代理newProxyInstance获取代理对象通过代理对象实现目标对象的功能特点 Java动态代理类中的invoke是怎么调用…

P8 RV1126推流 —— 摄像头和咪头模块初始化

前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_C…

对偶问题的基本性质

写于&#xff1a;2024年1月3日晚 修改于&#xff1a; 原规划与对偶规划 原规划对偶规划 max ⁡ z C T X s.t. { A X ≤ b , 其中 X ( m ∗ 1 ) X ≥ 0 \begin{aligned} & \max \mathrm{z}\mathbf{C}^T \mathbf{X} \\ & \text { s.t. }\left\{\begin{array}{l}\mat…

RFID在物流、供应链管理、工业自动化等领域的广泛应用

随着物联网技术的不断发展&#xff0c;RFID&#xff08;无线射频识别&#xff09;技术作为一种自动识别和跟踪技术&#xff0c;在物流、供应链管理、工业自动化等领域得到了广泛应用。本文将介绍RFID解决方案及其应用场景。 一、RFID技术概述 RFID是一种通过无线电波通信&…