首页 > 其他分享 >理解React页面渲染原理,如何优化React性能?

理解React页面渲染原理,如何优化React性能?

时间:2023-09-30 21:03:13浏览次数:40  
标签:key DOM 元素 React 渲染 组件 页面


React JSX转换成真实DOM过程

当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。

在运行React应用程序时,JSX会被转换成真实的DOM元素,这个过程主要涉及以下几个步骤:

  1. JSX代码编写: 你使用JSX语法编写React组件的界面结构。JSX允许你使用类似HTML的标记来描述UI层次结构,例如:
const element = <div>Hello, React!</div>;
  1. Babel转换: JSX语法并不是浏览器原生支持的,所以需要使用工具将JSX代码转换为浏览器可识别的JavaScript代码。通常会使用Babel这样的工具来进行这种转换。
    在上述示例中,JSX代码会被转换成类似以下的形式:
const element = React.createElement("div", null, "Hello, React!");

React.createElement 是一个用于创建React元素的函数,它接受标签名、属性和子元素作为参数。

  1. 创建虚拟DOM: 在转换后的JavaScript代码中,React.createElement 函数会创建一个称为虚拟DOM的JavaScript对象。虚拟DOM是React内部用来表示界面结构的一种轻量级表示形式。
  2. 虚拟DOM对比: 当状态发生变化导致界面需要更新时,React会使用虚拟DOM来比较前后两次状态的差异。这个过程被称为"协调。
  3. 生成真实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 性能优化的手段有哪些?

  1. 使用合适的组件: 将应用划分为合适的组件,每个组件关注特定功能。避免过大的组件,因为较小的组件更新更快。
  2. 使用PureComponent和React.memo: 使用PureComponentReact.memo来避免不必要的组件重新渲染,它们会在props或state没有变化时阻止不必要的渲染。
  3. 避免不必要的渲染: 通过使用shouldComponentUpdate生命周期方法或者函数组件的React.memo来控制组件是否需要重新渲染。
  4. 列表性能优化: 对于大型列表,使用列表虚拟化库(如react-virtualizedreact-windowreact-infinite-scroll-component)来仅渲染可见部分的数据,减少渲染开销。
  5. 使用key属性: 在渲染列表时,为每个子元素提供唯一的key属性,以帮助React准确地识别变化。
  6. 异步渲染: 使用React.lazySuspense实现组件的异步加载,从而减少初始加载时的资源消耗。
  7. 使用Memoization: 在函数组件中,使用useMemouseCallback来避免不必要的函数重新计算,减少渲染开销。
  8. 使用Immutability: 使用不可变数据结构来更新状态,以帮助React检测状态变化。这可以通过展开运算符、Object.assignArray.concat等方式实现。
  9. 组件拆分和懒加载: 将大型组件拆分成更小的子组件,并使用动态导入和代码分割来实现按需加载。
  10. 使用Profiler组件: React提供的<Profiler>组件可以帮助你识别渲染性能问题,并分析组件的渲染时间和调用次数。


标签:key,DOM,元素,React,渲染,组件,页面
From: https://blog.51cto.com/u_14196886/7664965

相关文章

  • 如何打开上古时期的“百度”页面
    无意之中解锁了百度的上古页面: 链接:https://www.baidu.com/default.html百度一下,你就知道(baidu.com)  ==========================================   可以说看到了这个页面就想到了20年前的百度,这个页面可以说百度的上古页面或者说是始祖页面了,现在的百度页面......
  • 填报页面提交方式:智能提交
    官方对只能提交的介绍:提交类型-FineReport帮助文档-全面的报表使用教程和学习资料(fanruan.com)从页面上识别到通过删除行动作删掉的数据,并根据设置的主键去数据库找到对应的数据进行删除。排除掉删除的数据后,对剩余数据根据设置的主键去数据库找对应的数据,如果有对应数......
  • 前端 | 如何处理 React18 componentDidMount 重复执行两次的问题 | React
    前端|如何处理React18componentDidMount重复执行两次的问题|React问题描述按照React官网推荐方式创建项目,在运行项目的时,发现组件的componentDidMount方法被触发了两次。但是在旧项目中并没有这样的问题,于是觉得奇怪,以为是自己哪里使用错了,一直在排查。经过查阅官方文......
  • 前端 | React setState 同步异步以及处理方式 | React
    前端|ReactsetState同步异步以及处理方式|React问题描述在同步执行流程中setState表现为异步,而在异步执行流程中setState表现为同步。示例:有一个控制DOM节点显隐的状态值,默认为false,而下一步就需要获取该DOM节点做一系类处理。所以一开始使用setState设置状态值为true,让该......
  • js:创建一个基于vite 的React项目
    相关文档Vite官方中文文档React中文文档ReactRouterRedux中文文档AntDesign5.0AwesomeReact创建vite+react项目pnpmcreatevitereact-app--templatereact#根据提示,执行命令cdreact-apppnpminstallpnpmrundev项目结构$tree-L1.├──README.md├──......
  • Java:Springboot和React中枚举值(数据字典)的使用
    目录1、开发中的需求2、实现效果3、后端代码4、前端代码5、接口数据6、完整代码7、参考文章1、开发中的需求开发和使用过程中,通常会涉及四个角色:数据库管理员、后端开发人员、前端开发人员、浏览者数据库使用int类型的数值进行存储(eg:0、1、2)Java代码使用enum枚举类型的对象进行......
  • openGL学习<三>、图形渲染管道(显示三角形)
    参考:https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/1、图形渲染管线2、顶点渲染器3、片段渲染器4、生成着色器程序5、 1、图形渲染管线图形渲染管线分为几个阶段小任务,对于每一个阶段任务程序(例如给10亿个像素着色),GPU都可以......
  • 小程序数组数据变化渲染的不是最新值?
    微信小程序切换后数据不是最新值如果是相同的key此时vue会跳过更新复用上次的dom和值,把第二个的别名item换成不相同的,比如item1,还不行就第二个的index换成index1key也换成index1<viewclass="queryCert-result-list"v-if="list.length>0"><viewclass="queryCert-result-list......
  • 关闭页面展示,运行selenium
    #关闭浏览器展示模式判断元素是否存在#导包fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromtimeimportsleepfromselenium.webdriver.chrome.optionsimportOptions#定义类classGetEle:def__init__(self,driver):......
  • React Native 动画(Animated)
    实现效果代码从react-native中引入import{Animated,Easing,}from'react-native';js实现constopacity1=useRef(newAnimated.Value(0.2)).current;constopacity2=useRef(newAnimated.Value(0.2)).current;constscale1=useRef(newAnimated.Valu......