理解React页面渲染原理,如何优化React性能?
React JSX转换成真实DOM过程
当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。
在运行React应用程序时,JSX会被转换成真实的DOM元素,这个过程主要涉及以下几个步骤:
-
JSX代码编写: 你使用JSX语法编写React组件的界面结构。JSX允许你使用类似HTML的标记来描述UI层次结构,例如:
const element = <div>Hello, React!</div>; -
Babel转换: JSX语法并不是浏览器原生支持的,所以需要使用工具将JSX代码转换为浏览器可识别的JavaScript代码。通常会使用Babel这样的工具来进行这种转换。
在上述示例中,JSX代码会被转换成类似以下的形式:
const element = React.createElement("div", null, "Hello, React!");React.createElement是一个用于创建React元素的函数,它接受标签名、属性和子元素作为参数。 -
创建虚拟DOM: 在转换后的JavaScript代码中,
React.createElement函数会创建一个称为虚拟DOM的JavaScript对象。虚拟DOM是React内部用来表示界面结构的一种轻量级表示形式。 -
虚拟DOM对比: 当状态发生变化导致界面需要更新时,React会使用虚拟DOM来比较前后两次状态的差异。这个过程被称为"协调。
-
生成真实DOM更新: 通过协调过程,React能够计算出哪些部分的DOM需要被更新。然后,它将针对实际需要更新的部分,生成一系列DOM操作,然后将其应用于浏览器的实际DOM上。这个过程是优化的,React会尽量最小化实际DOM操作的次数,以提高性能。
虚拟dom 与真实dom的区别
真实DOM: 真实DOM是浏览器实际生成的文档对象模型,它代表了网页的实际结构,由HTML元素组成,每个元素都有对应的属性和方法。当应用程序的状态发生变化时,直接操作真实DOM会导致浏览器进行重绘和重排,这是一种消耗性能的操作。更新真实DOM的频繁操作可能会导致性能问题,因为DOM操作是相对昂贵的操作,特别是在有大量元素需要更新时。
优点: 真实DOM是浏览器的基础,它可以完全呈现应用程序的状态,对于一些复杂的应用场景,真实DOM可能更能够准确地反映UI状态。
虚拟DOM: 虚拟DOM是一个轻量级的JavaScript对象,它是对真实DOM的抽象表示。它类似于真实DOM,但不是实际的网页结构,而是一个虚拟的副本。 当应用程序的状态发生变化时,React等库会首先在虚拟DOM上进行操作,然后通过比较前后两个虚拟DOM的差异,找出需要更新的部分,最终只会对真实DOM进行最小化的操作。
优点: 虚拟DOM的更新机制减少了对真实DOM的频繁操作,从而提高了性能。通过批量更新、合并操作等方式,可以有效减少重绘和重排的次数。
优缺点对比:
真实DOM优点:
- 它是浏览器的基础,可以准确地呈现应用状态。
- 适用于一些简单的应用,或者需要直接操作DOM的场景。
真实DOM 缺点:
- 更新时性能开销大,频繁的DOM操作会导致重排和重绘。
- 不适合大型或复杂的应用,容易导致性能问题。
虚拟DOM 优点:
- 提供了一种优化DOM更新的方式,减少了性能开销。
- 通过批量更新和最小化DOM操作,提高了应用的性能。
虚拟DOM 缺点:
- 虽然减少了DOM操作,但引入了额外的内存和计算开销,需要管理虚拟DOM树。
- 对于一些简单的应用或者性能不是关键问题的应用,引入虚拟DOM可能会过于复杂。
React中的key有什么作用?
相信在平时的开发中遇到过的警告warning: Each child in a list should have react.development.js:315 a unique "key" prop 。这就是在循环渲染的时候,如果忘记给元素加上key,浏览器给出警告。那么key到底有什么作用呢?
- 元素识别: key 用于帮助React识别列表中各个元素的唯一性。React使用 key 来判断哪些元素是新增、删除或更新的,从而进行高效的重渲染。
- 性能优化: 使用正确的 key 可以优化列表的更新性能。React会根据 key 判断元素是否需要重新渲染,从而避免不必要的重绘。
- 元素复用: 如果列表中的元素没有唯一的 key,React会难以识别元素之间的差异,从而可能导致错误的元素被重用,影响应用的正确性。
- 使用稳定的、与数据关联的 key 可以使得列表渲染的结果更加可预测。相同的数据对应相同的 key,从而更容易理解和追踪。
可以使用index作为key吗
绝大部分情况下使用 index 作为 key值,对性能没有优化。因为它可能导致性能问题和不稳定的渲染结果。
-
性能问题: 使用索引作为
key可能导致不必要的重绘和性能问题。当列表中的元素发生变化时,React可能会错误地认为相同索引处的元素没有变化,从而无法正确更新。 -
列表重排序问题: 当列表中的元素发生重新排序时,如果仅仅依赖于索引作为
key,可能会导致元素混乱,不符合预期。 -
动态添加和删除问题: 在列表中动态添加或删除元素时,使用索引作为
key可能导致React无法准确识别新增和删除的元素,从而导致错误的渲染。 -
不稳定的渲染结果: 使用索引作为
key可能导致不稳定的渲染结果。不同的渲染顺序可能会导致相同的数据在不同索引处渲染,从而引起错误。
React 性能优化的手段有哪些?
-
使用合适的组件: 将应用划分为合适的组件,每个组件关注特定功能。避免过大的组件,因为较小的组件更新更快。
-
使用PureComponent和React.memo: 使用
PureComponent和React.memo来避免不必要的组件重新渲染,它们会在props或state没有变化时阻止不必要的渲染。 -
避免不必要的渲染: 通过使用
shouldComponentUpdate生命周期方法或者函数组件的React.memo来控制组件是否需要重新渲染。 -
列表性能优化: 对于大型列表,使用列表虚拟化库(如
react-virtualized、react-window、react-infinite-scroll-component)来仅渲染可见部分的数据,减少渲染开销。 -
使用key属性: 在渲染列表时,为每个子元素提供唯一的
key属性,以帮助React准确地识别变化。 -
异步渲染: 使用
React.lazy和Suspense实现组件的异步加载,从而减少初始加载时的资源消耗。 -
使用Memoization: 在函数组件中,使用
useMemo和useCallback来避免不必要的函数重新计算,减少渲染开销。 -
使用Immutability: 使用不可变数据结构来更新状态,以帮助React检测状态变化。这可以通过展开运算符、
Object.assign、Array.concat等方式实现。 -
组件拆分和懒加载: 将大型组件拆分成更小的子组件,并使用动态导入和代码分割来实现按需加载。
-
使用Profiler组件: React提供的
<Profiler>组件可以帮助你识别渲染性能问题,并分析组件的渲染时间和调用次数。
相关文章:
理解React页面渲染原理,如何优化React性能?
React JSX转换成真实DOM过程 当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。 在运…...
数据通信——传输层TCP(可靠传输机制的滑动窗口)
引言 之前提到过拥塞问题,如果大量数据疯狂涌入,接收端无法及时处理就会导致数据丢包,从而使得通信受到干扰。之前的连续ARQ如果不加以节制,疯狂发送报文,接收端无法及时返回ACK就会导致网络瘫痪。 滑动窗口机制协议 这…...
Mycat之前世今生
如果我有一个32核心的服务器,我就可以实现1个亿的数据分片,我有32核心的服务器么?没有,所以我至今无法实现1个亿的数据分片。——MyCAT ‘s Plan 话说“每一个成功的男人背后都有一个女人”,自然MyCAT也逃脱不了这个诅…...
Linux- 重定向标准输出(stdout)和标准错误(stderr)
在Linux或Unix系统中,可以通过重定向标准输出(stdout)和标准错误(stderr)来将脚本的输出保存到一个文件中。以下是一些方法: 只重定向标准输出到文件: ./your_script.sh > output.txt这将只捕…...
PostgreSQL分区表
什么是分区表 数据库分区表将表数据分成更小的物理分片,以此提高性能、可用性、易管理性。分区表是关系型数据库中比较常见的对大表的优化方式,数据库管理系统一般都提供了分区管理,而业务可以直接访问分区表而不需要调整业务架构,…...
android framework之Applicataion启动流程分析(二)
上一篇讲了Zygote是如何收到启动Application的启动消息,并一步步进入Fork(),下面来分析zygote fork启动application后,application进程后续处理操作,是如何真正的启动的。 ZygoteInit.main():-->...caller ZygoteServer.runSelectLoop()…...
django静态文件无法访问解决方案
nginx配置如下: # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/user nginx; worker_processes auto; error_log /var/log/ng…...
WIndows 配置多版本python环境,非常清晰明了
配置多个python环境 下面以配置三个python版本环境为例子 首先下载好三个环境的python,如:python2.7、python3.6、python3.10 给个官网链接自己下,想要几版本就下几:https://www.python.org/downloads/windows/ 下载完成后将pyth…...
Leetcode每日一题:1267. 统计参与通信的服务器(2023.8.24 C++)
目录 1267. 统计参与通信的服务器 题目描述: 实现代码与解析: 写法一:两次遍历 hash 原理思路: 写法二:三次遍历 原理思路: 1267. 统计参与通信的服务器 题目描述: 这里有一幅服务器分…...
c++(8.28)菱形继承,虚继承,多态,抽象类,模板+Xmind
xmind: 作业: 1.编程题: 以下是一个简单的比喻,将多态概念与生活中的实际情况相联系: 比喻:动物园的讲解员和动物表演 想象一下你去了一家动物园,看到了许多不同种类的动物,如狮子、大象、猴…...
安装部署JavaFX和IDEA添加JavaFX的详细步骤
安装部署JavaFX和IDEA添加JavaFX的详细步骤 一、认识JavaFX二、下载JavaFX三、解压到目录下四、IDEA导入JavaFX五、添加JavaFX的VM选项六、运行命令七、总结一、认识JavaFX JavaFX是Java平台的一个图形用户界面(GUI)工具包,用于创建丰富、交互式和可视化的应用程序。JavaFX提…...
MAC电脑外放没有声音解决方案
烦人呐,我的mac外接显示屏幕,显示器没有音频输出,需要mac笔记本的音频输出,但是经常打开后,mac没有声音输出,需要重启电脑才能生效。亲测一下方法有效,请参考: 文章目录 一、短期方案…...
Spring源码分析(八)CreateBean与DoCreateBean
写目录 一 CreateBean二 doCreateBean2.1 BeanWrapper2.2 缓存删除2.3 实例化Bean2.3.1 Supplier创建对象2.3.2 工厂创建对象2.3.3 构造器创建实例无参构造构造器依赖注入Setter的依赖注入autowireConstructor实例化instantiateBean 方法 2.4 Bean的前置处理 官网:H…...
iSCSI存储服务器
目录 一、ISCSI是什么? 二、ISCSI产生背景 三、存储分类 四、ISCSI架构 五、ISCSI存储服务搭建案例 一、ISCSI是什么? ISCSI名为互联网小型计算机系统接口又称为IP-SAN,是一种新的远程存储技术,提供存储服务的目标服务器默认使用的…...
信息技术02--初/高中--分类选择题(377道题与解析)
文章目录 第一章 办公软件 1-96第二章 信息技术基础 1-41第三章 计算机系统基础 1-28第四章 多媒体技术 1-115第五章 计算机网络技术 1-50第六章 信息安全 1-3第七章 算法与程序简介 1-13第八章 数据结构 1-2第九章 数据库技术 1-20第十章 练习 1-9 第一章 办公软件 1-96 1、某…...
java --- 枚举类
目录 一、枚举类 二、创建枚举类 2.1、JDK5.0之前创建 2.2、JDK5.0使用enum创建 三、枚举类常用方法 四、枚举类实现接口 一、枚举类 枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。 二、创建枚举类 …...
nvm和volta对node版本控制的区别
前言——我们做前端开发的都会需要node.js环境,我们直接安装指定的版本可以么?可以,只不过在需要换版本的时候还得卸载重新装。那有工具可以帮助我们不用卸载就更改node版本么?有啊,nvm就可以。那又有没有什么工具不用…...
高斯消元解线性方程组
思路: (1)模拟线性代数解方程组办法,在此讨论正方形方程组求解。 (2)考虑几个问题: 数据存储:采用double数组存储。判断是否为零,由于double计算存在误差,…...
【linux命令讲解大全】032.介绍 Linux 中的 rcp 命令:简化主机间文件复制操作
文章目录 rcp补充说明语法选项参数实例rcp命令使用条件 从零学 python rcp 使在两台Linux主机之间的文件复制操作更简单 补充说明 rcp命令使在两台Linux主机之间的文件复制操作更简单。通过适当的配置,在两台Linux主机之间复制文件而无需输入密码,就像…...
Mysql索引、事务与存储引擎 (事务、MySQL 存储引擎)
事务 一、事务的概念: ①事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。 ②事务是一个不可分割的工…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...
前端打包工具简单介绍
前端打包工具简单介绍 一、Webpack 架构与插件机制 1. Webpack 架构核心组成 Entry(入口) 指定应用的起点文件,比如 src/index.js。 Module(模块) Webpack 把项目当作模块图,模块可以是 JS、CSS、图片等…...
