React 组件性能优化

React 组件性能优化的核心减少渲染真实 DOM 节点的频率,减少 Virtual DOM 比对的频率。

1. 组件卸载前进行清理操作

window 注册的全局事件, 以及定时器

useEffect(()=>{
	return ()=>{
		// do something
		clearTimeout(tiemr)
		 window.removeEventListener('xxx', calback)
	}
},[])

2. PureComponent

  1. 什么是纯组件
    纯组件会对组件输入数据进行浅层比较,如果当前输入数据和上次输入数据相同组件不会重新渲染
  2. 什么是浅层比较
    比较引用数据类型在内存中的引用地址是否相同,比较基本数据类型值是否相同
  3. 如何实现纯组件
    类组件继承 PureComponent 类,函数组件使用 memo 方法
  4. 为什么不直接进行 diff 操作, 而是要先进行浅层比较,浅层比较难道没有性能消耗吗?
    和进行 diff 比较操作相比,浅层比较将消耗更少的性能。diff 操作会重新遍历整颗 virtualDOM 树, 而浅层比较只操作当前组件的 state 和 props。

3. shouldComponentUpdate

纯组件只能进行浅层比较,要进行深层比较,使用 shouldComponentUpdate,它用于编写自定义比较逻辑。

返回 true 重新渲染组件,返回 false 阻止重新渲染。

函数的第一个参数为 nextProps, 第二个参数为 nextState.

 shouldComponentUpdate(nextProps, nextState) {
    if (this.state.name !== nextState.name || this.state.age !== nextState.age) {
      return true
    }
    return false
  }

4. React.memo

为 memo 传递比较逻辑

使用 memo方法自定义比较逻辑,用于执行深层比较。

比较函数的第一个参数为上一次的 props, 比较函数的第二个参数为下一次的 props, 比较函数返回 true, 不进行渲染, 比较函数返回 false, 组件重新渲染.

    const ShowPersonMemo = memo(ShowPerson, comparePerson)
   
   function comparePerson(prevProps, nextProps) {
     if (
       prevProps.person.name !== nextProps.person.name ||
       prevProps.person.age !== nextProps.person.age
     ) {
       return false
     }
     return true
   }

5. 使用组件懒加载

使用组件懒加载可以减少 bundle 文件大小, 加快组件呈递速度.

  1. 路由组件懒加载
 import React, { lazy, Suspense } from "react"
 import { BrowserRouter, Link, Route, Switch } from "react-router-dom"
 // 打包时生成对应名字的chunk
 const Home = lazy(() => import(/* webpackChunkName: "Home" */ "./Home"))
 const List = lazy(() => import(/* webpackChunkName: "List" */ "./List"))
 
 function App() {
   return (
     <BrowserRouter>
       <Link to="/">Home</Link>
       <Link to="/list">List</Link>
       <Switch>
       // 组件未加载完成展示loading
         <Suspense fallback={<div>Loading</div>}>
           <Route path="/" component={Home} exact />
           <Route path="/list" component={List} />
         </Suspense>
       </Switch>
     </BrowserRouter>
   )
 }
    
 export default App
  1. 根据条件进行组件懒加载

    适用于组件不会随条件频繁切换

    import React, { lazy, Suspense } from "react"
    
    function App() {
      let LazyComponent = null
      if (true) {
        LazyComponent = lazy(() => import(/* webpackChunkName: "Home" */ "./Home"))
      } else {
        LazyComponent = lazy(() => import(/* webpackChunkName: "List" */ "./List"))
      }
      return (
        <Suspense fallback={<div>Loading</div>}>
          <LazyComponent />
        </Suspense>
      )
    }
    
    export default App
    

6. 使用 Fragment 避免额外标记

7. 不要使用内联函数定义

8. 在构造函数中进行函数this绑定

9. 类组件中的箭头函数

10. 避免使用内联样式属性

11. 优化条件渲染

12. 为组件创建错误边界

错误边界涉及到两个生命周期函数, 分别为 getDerivedStateFromErrorcomponentDidCatch.
– getDerivedStateFromError 为静态方法, 方法中需要返回一个对象, 该对象会和state对象进行合并, 用于更改应用程序状态.

– componentDidCatch 方法用于记录应用程序错误信息. 该方法的参数就是错误对象.
ErrorBoundaries.js

import React from "react"
import App from "./App"
export default class ErrorBoundaries extends React.Component {
  constructor() {
    super()
    this.state = {
      hasError: false
    }
  }
  componentDidCatch(error) {
    console.log("componentDidCatch")
  }
  static getDerivedStateFromError() {
    console.log("getDerivedStateFromError")
    return {
      hasError: true
    }
  }
  render() {
    if (this.state.hasError) {
      return <div>发生了错误</div>
    }
    return <App />
  }
}

App.js

import React from "react"
export default class App extends React.Component {
  render() {
    // throw new Error("lalala")
    return <div>App works</div>
  }
}

index.js

import React from "react"
import ReactDOM from "react-dom"
import ErrorBoundaries from "./ErrorBoundaries"
ReactDOM.render(<ErrorBoundaries />, document.getElementById("root"))

注意: 错误边界不能捕获异步错误, 比如点击按钮时发生的错误.

13. 避免数据结构突变

14. 依赖优化

主要是对包进行优化
参考:重构之路:webpack打包体积优化(超详细)

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

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

相关文章

基于深度学习检测恶意流量识别框架(80+特征/99%识别率)

基于深度学习检测恶意流量识别框架 目录 基于深度学习检测恶意流量识别框架简要示例a.检测攻击类别b.模型训练结果输出参数c.前端检测页面d.前端训练界面e.前端审计界面&#xff08;后续更新了&#xff09;f.前端自学习界面&#xff08;自学习模式转换&#xff09;f1.自学习模式…

Spring管理第三方依赖

在开发中&#xff0c;我们常需要根据业务需求导入我们需要的第三方依赖包&#xff0c;本文主要以导入druid数据库来连接池为案例讲解有关spring管理第三方依赖 目录 纯注解文件注入 1.在pom.xml中导入依赖 2.在com.lcyy包下建立一个config包用于配置类的实现 3.在config包下…

2024年第十五届蓝桥杯江苏省赛回顾

呜呜呜~~~ 我在考完了后感觉自己直接炸了&#xff1a;好多学到的算法都没有用上&#xff0c;几乎所有的题目都是暴力的。。。 最后十几分钟对于一道dp算法终于有思路了&#xff0c;但是。。匆匆忙忙之间就是没有调试出来。&#xff08;还是交了一道暴力[旋风狗头]直接哭死~~&…

微信小程序开发核心:样式,组件,布局,矢量图标

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Zynq 7000 系列之启动模式—NAND启动

NAND启动是一种使用NAND闪存进行设备启动的方式。NAND闪存是一种非易失性存储设备&#xff0c;广泛用于嵌入式系统、计算机和其他电子设备中。由于NAND闪存具有高速读写和较高的存储密度等特点&#xff0c;使得NAND启动成为了一种高效且常用的启动方式。 1 特点 NAND启动具有…

【Spring】Spring中AOP的简介和基本使用,SpringBoot使用AOP

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 一、AOP简介 AOP的全称是Aspect-Oriented Programming&#xff0c;即面向切面编程&#xff08;也称面向方面编程&#xff09;。它是面向对象编程&#xff08;OOP&#xff09;的一种补充&#xff0c;目前已成为一种比较成…

Milvus Cloud 向量数据库Reranker成本比较和使用场景

成本比较:向量检索 v.s. Cross-encoder Reranker v.s. 大模型生成 虽然 Reranker 的使用成本远高于单纯使用向量检索的成本,但它仍然比使用 LLM 为同等数量文档生成答案的成本要低。在 RAG 架构中,Reranker 可以筛选向量搜索的初步结果,丢弃掉与查询相关性低的文档,从而有…

电商技术揭秘三十九:电商智能风控技术架构设计

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

简单分享,豆瓣小组,可能被你忽视的获取精准流量渠道!

⾖瓣⼩组&#xff1a;精准流量的隐藏宝藏 探索互联网世界的每一个角落&#xff0c;你会发现总有那么一些被忽视的宝藏&#xff0c;等待着被发现者的光临。今天&#xff0c;我要和大家分享的这个宝藏&#xff0c;就是⾖瓣⼩组——一个你可能未曾注意到的精准流量渠道。 ⾖瓣平…

2024最新UI发卡盗U/支持多语言/更新UI界面/支持多个主流钱包

本文来自&#xff1a;2024最新UI发卡盗U/支持多语言/更新UI界面/支持多个主流钱包 - 源码1688 应用介绍 简介&#xff1a; 2024最新UI发卡盗U/支持多语言/更新UI界面/支持多个主流钱包 自行检查后门&#xff0c;最好是部署智能合约后用合约地址来授权 包含转账支付页面盗U授…

蓝网科技临床浏览系统 deleteStudy SQL注入漏洞复现(CVE-2024-4257)

0x01 产品简介 蓝网科技临床浏览系统是一个专门用于医疗行业的软件系统,主要用于医生、护士和其他医疗专业人员在临床工作中进行信息浏览、查询和管理。 0x02 漏洞概述 蓝网科技临床浏览系统 deleteStudy接口处SQL注入漏洞,未经身份验证的恶意攻击者利用 SQL 注入漏洞获取…

HEVC/H.265视频编解码学习笔记–框架及块划分关系

前言 由于本人在学习视频的过程中&#xff0c;觉得分块单元太多搞不清楚其关系&#xff0c;因此本文着重记录这些分块单元的概念以及关联。 一、框架 视频为一帧一帧的图像&#xff0c;其编码的主要核心是压缩空间以及时间上的冗余。因此&#xff0c;视频编码有帧内预测和帧间…

TCP协议在物联网中实战

一、TCP协议介绍 网上对TCP协议介绍众多&#xff0c;本人按照自己的理解简单介绍一下。 TCP&#xff08;Transmission Control Protocol&#xff0c; 传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输控制层通信协议。 1.1 协议机制 1.1.1 三次握手 &…

面试重点1:打开网页点击URL,返回页面内容,从网络协议层面讲解一下

在这种场景下&#xff0c;从网络协议层面来讲解打开网页并点击 URL 的过程可以大致分为以下几个步骤&#xff1a; 1. DNS 解析 当你在浏览器中输入一个 URL&#xff08;例如 https://www.example.com&#xff09;&#xff0c;首先浏览器会进行 DNS 解析&#xff0c;将域名解析…

前端VUE项目中使用async()用法是为什么?能不用吗?

使用 async 关键字来定义一个函数主要有几个原因&#xff1a; 支持 await 关键字&#xff1a; async 函数允许你在其中使用 await 关键字&#xff0c;这使得你可以在不阻塞程序执行的情况下&#xff0c;等待一个异步操作&#xff08;如网络请求、文件读写等&#xff09;的完成。…

JAVA基础---Stream流

Stream流出现背景 背景 在Java8之前&#xff0c;通常用 fori、for each 或者 Iterator 迭代来重排序合并数据&#xff0c;或者通过重新定义 Collections.sorts的 Comparator 方法来实现&#xff0c;这两种方式对 大数量系统来说&#xff0c;效率不理想。 Java8 中添加了一个…

Python量化炒股的获取数据函数—get_concept()

查询股票所属的概念板块函数get_concept()&#xff0c;利用该函数可以查询一只或多只股票所属的概念板块&#xff0c;其语法格式如下&#xff1a; get_concept(security, dateNone)security&#xff1a;标的代码。类型为字符串&#xff0c;形式如‘000001.XSHE’&#xff0c;或…

邦注科技 模具清洗机 干冰清洗机 干冰清洗设备原理介绍

干冰清洗机&#xff0c;这款神奇的清洁设备&#xff0c;以干冰颗粒——固态的二氧化碳&#xff0c;作为其独特的清洁介质。它的工作原理可谓独具匠心&#xff0c;利用高压空气将干冰颗粒推送至超音速的速度&#xff0c;犹如一颗颗银色的流星&#xff0c;疾速喷射至待清洗的物体…

攻防世界XCTF-WEB入门12题解题报告

WEB入门题比较适合信息安全专业大一学生&#xff0c;难度低上手快&#xff0c;套路基本都一样 需要掌握&#xff1a; 基本的PHP、Python、JS语法基本的代理BurpSuite使用基本的HTTP请求交互过程基本的安全知识&#xff08;Owasp top10&#xff09; 先人一步&#xff0c;掌握W…

基准测试函数表达式--单峰函数与多峰函数

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…