【前端知识】React 基础巩固(二十三)——React 性能优化 SCU相关

React 基础巩固(二十三)——React 性能优化 SCU

React 更新机制

  • React 的渲染流程

    • JSX -> 虚拟 DOM -> 真实 DOM
  • React 的更新流程

    • props/state 改变 -> render函数重新执行 -> 产生新的DOM树 -> 新旧DOM树进行diff -> 计算出差异进行更新 -> 更新到真实的DOM
  • React 在 props 或 state 发生改变时,会调用 React 的 render 方法,会创建一颗不同的树

  • React 需要基于这两颗不同的树之间的差别来判断如何有效的更新 UI

    • 如果一颗树参考另外一颗树进行完全比较更新,那么即使时最先进的算法,该算法的复杂度为 O(n^2),其中 n 是树中元素的数量;
    • 如果在 React 中使用了该算法,那么展示 1000 个元素所需要执行的计算量将在 10 亿的量级范围;
    • 开销过于昂贵,更新性能非常低效;
  • 于是,React 对这个算法进行了优化,将其优化成了 O(n)

    • 同层节点之间相互比较,不会跨节点比较
    • 不同类型的节点,产生不同的树结构
    • 开发中,可以通过 key 来指定哪些节点在不同的渲染下保持稳定
  • keys 的优化

    • 遍历列表时,会提示一个警告,提示我们加入一个 key 属性
    • 当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素
      • 例如将 key 为 333 的元素插入到最前面的位置时,key 为 111,222 的元素,仅仅需要进行位移即可,不需要任何修改
  • key 的注意事项

    • key 应该是唯一的
    • key 不要使用随机数(随机数在下一次 render 时,会重新生成一个数字)
    • 使用 index 作为 key,对性能是没有优化的
  • render 函数被调用

    • 为了避免不必要的 render,提高性能,调用 render 应该有一个前提:依赖的数据(state、props)发生改变时,再调用 render 方法
  • 利用shouldComponentUpdate优化 render 调用


// 针对值发生变化的组件
shouldComponentUpdate(nextProps, newState){// 对比 state中的值是否有改变if (this.state.message !== newState.message || this.state.counter !== newState.counter){return true}return false
}// 针对其中的子组件
shouldComponentUpdate(nextProps, newState){// 1.对比 state中的值是否有改变if (this.state.message !== newState.message || this.state.counter !== newState.counter){return true}// 2.检测接收的props是否有改变if (this.props.message !== newProps.message){return true}return false
}
  • 如果参数过多,SCU 的方式则过于繁琐,所以通常采用以下方式实现

针对类组件:采用PureComponent 实现优化

import React, { PureComponent } from "react";
export class App extends PureComponent {// ...
}

PureComponent中变更数组数据的实际应用:

import React, { PureComponent } from "react";export class App extends PureComponent {constructor() {super();this.state = {books: [{ name: "book1", price: 199, count: 1 },{ name: "book2", price: 299, count: 1 },{ name: "book3", price: 399, count: 2 },{ name: "book4", price: 499, count: 3 },{ name: "book5", price: 599, count: 1 },],};}addNewBook() {const newBook = {name: "book6",price: 55,count: 1,};// 错误写法:// 直接修改原有的state,重新设置一遍// this.state.books.push(newBook);// this.setState({//   books: this.state.books,// });// 正确写法:// 拷贝一份,在新的数组中更新,设置新的books,而不是直接修改stateconst books = [...this.state.books];books.push(newBook);this.setState({ books });}addBookCount(index) {console.log(index);const books = [...this.state.books];books[index].count++;this.setState({ books });}render() {const { books } = this.state;return (<div><h2>books list</h2><ul>{books.map((item, index) => {return (<li key={index}><span>name: {item.name} - price: {item.price} - count: {item.count}</span><button onClick={(e) => this.addBookCount(index)}>+1</button></li>);})}</ul><button onClick={(e) => this.addNewBook()}>添加新书籍</button></div>);}
}export default App;

针对函数式组件:采用 memo 实现优化

import { memo } from "react";
const Profile = memo(function (props) {console.log("profile render");return <h2>Profile: {props.message}</h2>;
});export default Profile;

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

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

相关文章

Element分页组件自定义样式

样式效果 页面代码 <el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-page"page.page":page-sizes"[10, 20, 30, 40]":page-size"page.size"layout"total, sizes, prev, …

如何用https协议支持小程序

步骤一&#xff1a;下载SSL证书 登录数字证书管理服务控制台。在左侧导航栏&#xff0c;单击SSL 证书。在SSL证书页面&#xff0c;定位到目标证书&#xff0c;在操作列&#xff0c;单击下载。 在服务器类型为Nginx的操作列&#xff0c;单击下载。 解压缩已下载的SSL证书压缩…

Python中Threading对于TCP的使用

什么是多线程&#xff1f; 多线程类似于同时执行多个不同程序&#xff0c;多线程运行有如下优点&#xff1a; 使用线程可以把占据长时间的程序中的任务放到后台去处理。 用户界面可以更加吸引人&#xff0c;这样比如用户点击了一个按钮去触发某些事件的处理&#xff0c;可以弹…

springboot经典面试题2

问题&#xff1a;什么是Spring Boot的起步依赖&#xff08;Starter Dependencies&#xff09;&#xff1f;如何使用起步依赖&#xff1f; 答案&#xff1a;Spring Boot的起步依赖是一组预定义的依赖项&#xff0c;可以简化项目的配置和构建过程。可以通过在项目的构建配置文件…

[个人笔记] WinSrv批量添加DNS记录和条件转发器记录

Windows Server - 运维篇 第三章 WinSrv批量添加DNS记录和条件转发器记录 Windows Server - 运维篇系列文章回顾WinSrv批量添加DNS记录和条件转发器记录单条记录添加DNS条件转发器记录批量新增DNS条件转发器记录批量导出DNS条件转发器 参考来源 系列文章回顾 第一章 域控使用C…

使用 jmeter 进行审批类接口并发测试

目录 前言&#xff1a; 背景&#xff1a; 难点&#xff1a; 场景 a&#xff1a; 场景 b&#xff1a; 前言&#xff1a; 使用JMeter进行审批类接口的并发测试是一种有效的方法&#xff0c;可以模拟多个用户同时对接口进行审批操作&#xff0c;以评估系统在高负载情况下的性…

Java+Vue+Uniapp全端WMS仓库管理系统

详情图片为运行截图,功能列表: 1、数据管理:物料数据管理、物料Bom管理、物料组管理、物料分类管理、供应商管理、仓库管理、货位管理、车间管理 2、采购管理:物料标签管理、入库单管理、入库退货管理 3、质检管理:质检单管理(包括单据号、单据类型、创建时间、检验状态…

4. CSS用户界面样式

4.1什么是界面样式 所谓的界面样式,就是更改一些用户操作样式,以便提高更好的用户体验。 ●更改用户的鼠标样式 ●表单轮廓 ●防止表单域拖拽 4.2鼠标样式cursor li {cursor: pointer; }设置或检索在对象上移动的鼠标指针采用何种系统预定义的光标形状。 4.3轮廓线outline…

Mac如何将homebrew添加到系统路径

1.在终端下进入路径配置文件 sudo vim .zprofile 2.输入用户密码进入文本&#xff0c;键盘按i进入编辑模式&#xff08;左下角会显示INSERT状态&#xff09;&#xff0c;配置环境变量&#xff1a; export PATH/opt/homebrew/bin:$PATH3.Esc退出编辑模式&#xff0c;输入**&am…

排序算法第三辑——交换排序

目录 ​编辑 一&#xff0c;交换排序算法的简介 二&#xff0c;冒泡排序 冒泡排序代码&#xff1a;排升序 三&#xff0c;快速排序 1.霍尔大佬写的快速排序 2.挖坑法 3.前后指针法 四&#xff0c;以上代码的缺陷与改正方法 三数取中 三路划分&#xff1a; 五&#…

【电子学会】2023年05月图形化四级 -- 计算圆的面积和周长

计算圆的面积和周长 编写程序计算圆的面积和周长。输入圆的半径&#xff0c;程序计算出圆的面积和周长&#xff0c;圆的面积等于3.14*半径*半径&#xff1b;圆的周长等于2*3.14*半径。 1. 准备工作 &#xff08;1&#xff09;保留舞台中的小猫角色和白色背景&#xff1b; 2…

Stream流式思想

什么是Stream&#xff1f; 也叫Stream流&#xff0c;是Jdk8开始新增的一套API (java.util.stream.*)&#xff0c;可以用于操作集合或者数组的数据。 优势&#xff1a; Stream流大量的结合了Lambda的语法风格来编程&#xff0c;提供了一种更加强大&#xff0c;更加简单的方式操…

从 Blender 导出动画视频

Blender Tutorial - How To Export Video Files 要导出编辑完的视频&#xff0c;你需要先设置好输出的格式、分辨率、帧率、位置等参数&#xff0c;然后选择渲染动画的选项&#xff0c;等待渲染完成后&#xff0c;你就可以在指定的位置找到生成的视频文件。 具体步骤如下&…

Python 列表 sort()函数使用详解

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 sort函数使用详解 1、升序降序2、sort()和sorted()的区别3、切片排序4、指定排序…

vue封装短信验证码,刷新缓存倒计时

HTML代码 <a-form-item field"verifyCode" label"验证码:"><a-input v-model"formData.verifyCode" placeholder"短信验证码" class"login-form-button" allow-clear><template #append><span:class&q…

TypeScript笔记

文章目录 什么是TS前期准备安装TSTS配置文件 基础类型原始类型 object类型 数组类型 元组类型 枚举 函数类型可选参数和默认参数剩余参数 any任意类型 高级类型交叉类型联合类型 接口类泛型类型别名参考 什么是TS 官网介绍&#xff1a;TypeScript是JavaScript类型的超集&#…

力扣160. 相交链表

题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。题目数据保证整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&#xff0c;链表必须保持其原始结构。 链接&am…

深度学习项目四:创建自定义数据集的dataset, DataLoader

深度学习项目四:创建自定义数据集的dataset, DataLoader 文章目录 深度学习项目四:创建自定义数据集的dataset, DataLoader前言一、构建dataset基本类二、创建train_dataset,test_dataset及相应DataLoader1.数据集的index创建2.创建自定义dataset类3.划分训练集和测试集,创建…

Qt应用程序性能优化总结

在Qt中进行性能优化时&#xff0c;可以考虑以下建议来提高应用程序的性能&#xff1a; 1. 使用合适的数据结构&#xff1a;选择适当的数据结构对于提高性能至关重要。例如&#xff0c;使用QList而不是QVector来存储大量数据时&#xff0c;可以提高插入和删除的性能。另外&…

飞书ChatGPT机器人 – 打造智能问答助手实现无障碍交流

文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话&#xff0c;在下面操作步骤中…