react性能优化

2023-10-26

写在前面的话:

要想解决问题,首先得找到问题的根源,所以,说起性能分析,还是要从其生命周期和渲染机制说起。


1.渲染机制

react的组件渲染分为初始化渲染和更新渲染,在初始化渲染的时候会调用根组件下的所有组件的render方法进行渲染。

但是当我们要更新某个子组件的时候,是从根组件传递下来应用在子组件上的数据发生改变。
我们只是希望调用关键路径上组件的render就好了。
但是,
react的默认做法是调用所有组件render,再对生成的虚拟DOM进行对比,如不变就不进行更新。这样的render和虚拟DOM的对比明显实在浪费时间。
注意:

拆分组件是有利于复用和组件优化的,其次,生成虚拟DOM并进行对比发生在render之后,而不是render之前。

总得来说,父亲组件的props和state发生变化时,他和他的子子孙孙组件等后代都要重新渲染。

2.更新阶段的生命周期

这里写图片描述
1.componementWillReceiveProp:当挂载的组件接受到新的props时会被调用,此方法应该被用于比较this.props和nextProps以用于使用this.setState()执行状态转换,(组件内部数据有变化,使用state,但是在更新阶段又要在props改变的时候改变state,则在这个生命周期里面)

2.shouldComponentUpdate:当组件决定任何改变是否要更新到DOM时被调用,作为一个优化实现比较this.props和nextProps,this.state和nextState,如果应该跳过更新,返回false。

3.componentWillUpdate:在更新发生前被立即调用,此时不能调用this.setState()

4.componentDidUpdate:在更新发生后被立即调用。(可以在DOM更新完之后,做一些收尾工作)

react的优化是基于shouldComponentUpdate的,该生命周期默认返回true,所以一旦prop或state有任何变化,都会引起重新render。

所以,可以得出react的性能优化就是围绕shouldComponentUpdate(SCU)方法来进行的,其优化无外乎两点:

  • 缩短SCU方法的执行时间(或者直接不执行)
  • 没必要的渲染,SCU就该返回false

shouldComponentUpdate:

react在每个组件生命周期更新的时候都会调用一个shouldComponentUpdate(nextprops,nextState)函数,他的职责就是返回true,或者false,true表示需要更新,false就是表示不需要,默认值是返回true的,即便你没有显示的定义shouldComponentUpdate函数,他的返回值还是true。

根据渲染流程,首先会判断shouldcomponentUpdate是否需要更新,如果需要更新,则调用组件的render生成新的虚拟DOM,然后再与旧的虚拟DOM进行对比,如果对比一致就不更新,如果对比不同,则根据最小粒度改变去更新DOM,如果scu不需要更新,则直接保持不变,同时其子元素也保持不变。

注意:错误写法

  • {…this.props}(不能滥用,只传递component需要的props即可,传递的太多,或者层次传的太深,都会加重shuoldComponentUpdate,其里面的数据比较负担,因此一定要慎重使用spread attributes(<Component {...props}/>))
  • ::this.handleChange()(将该方法的bind一律置于constructor)
  • 复杂的页面不要在一个组件中写完
  • 尽量使用const element定义
  • map里面添加key,并且key不要使用index(可变的)
  • 尽量少的使用setTimeout或者不可控的refs,DOM操作
  • props和state的数据尽可能简单明了,扁平化。
  • 使用return null而不是css的display:none来控制节点的隐藏。保证同一时间页面的DOM节点尽可能的少。

3.性能分析工具

React特色工具:Perf

react官方提供一个插件react.addons.perf可以帮助我们分析组件的性能,以确认是否需要优化。

Perf 是react官方提供的性能分析工具。Perf最核心的方法莫过于Perf.printWasted(measurements),该方法会列出那些没必要的组件渲染。很大程度上,React的性能优化就是干掉这些无谓的渲染。

操作:
打开console面板,先输入Perf.start()执行一些组件操作,引起数据变动,组件更新,然后输入Perf.stop()。(建议一次只执行一个操作,好进行分析)
然后在输入Perf.printInclusive将所有涉及到的组件render打印下来。(官方图片)
这里写图片描述
或者输入Perf.printWasted()查看不需要的浪费组件的render。
这里写图片描述

优化前:
这里写图片描述
优化后:
这里写图片描述

4.其它检测工具

react-perf-tool为react提供了一种可视化的性能检测方案,其同样是基于React.addons,但是使用图标来显示结果更加方便。

1.PureRenderMixin(基于es5)

var PureRenderMixin = require('react-addons-pure-render-mixin');
React.createClass({
  mixins: [PureRenderMixin],

  render: function() {
    return <div className={this.props.className}>foo</div>;
  }
});

2.Shallow Compare(基于es6)

var shallowCompare = require('react-addons-shallow-compare');
export class SampleComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState);
  }

  render() {
    return <div className={this.props.className}>foo</div>;
  }
}

pureRender很简单,就是把穿进来的component的shouldComponentUpdate给重写掉,原来的shouldComponentUpdate,无论怎样都是return true,现在不会这样了,我要用shallowCompare比一比,shallowCompare代码及其简单,如下:

function shallowCompare(instance, nextProps, nextState) {
  return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState);
}

但是这样做还是有缺点的:
shallowEqual其实只比较props的第一层,子属性是不是相同,如果props是如下:

{
  detail: {
    name: "123",
    age: "123"
  }
}

他只会比较props.detail===nextProps.detail,这就会导致在传入复杂的数据的情况下,优化会失效。

7.补充

react在15.3.0里面加入了react.PureComponent一个可继承的新的基础类,用来替换react-addons-pure-render-mixin,用法如下:

class CounterButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}

8.immutable.js

我们也可以在shouldComponentUpdate()中使用deepCopy和deepCompare来避免无必要的render(),但是deepCopy和deepCompare一般都是非常耗性能的。

Immutable Date就是一旦创建,就不能再被更改的数据。对Immutable对象的任何修改或者添加删除操作都会返回一个新的Immutable对象。

Immutable实现的原理是Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变,同时为了避免deeepCopy把所有的节点都复制一遍带来的性能损耗,Immutable使用了,Structural Sharing(结构共享)即如果对象树中一个节点发生变化,只修改这个节点和受他影响的父节点,其他节点则进行共享。

Immutable则提供了简洁高效的判断数据是否变化的方法,只需要===和is比较就能知道是否需要执行render(),而这个操作几乎0成本,所以可以极大提高性能,修改后的shouldComponentUpdate是这样的:

import { is } from 'immutable';

shouldComponentUpdate: (nextProps = {}, nextState = {}) => {
  const thisProps = this.props || {}, thisState = this.state || {};

  if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
      Object.keys(thisState).length !== Object.keys(nextState).length) {
    return true;
  }

  for (const key in nextProps) {
    if (!is(thisProps[key], nextProps[key])) {
      return true;
    }
  }

  for (const key in nextState) {
    if (thisState[key] !== nextState[key] || !is(thisState[key], nextState[key])) {
      return true;
    }
  }
  return false;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react性能优化 的相关文章

  • 值得收藏的UmiJS 教程

    点击上方关注 前端技术江湖 一起学习 天天进步 前言 网上的umi教程是真的少 很多人都只写了一点点 很多水文 所以打算自己写一篇 自己搭建umi 并封装了一下常用的功能 并用到公司实际项目中 umi介绍 Umi 是什么 Umi 中文可发音
  • perf-report显示CPU寄存器的值

    我跟随这个文件并使用perf record with intr regs ax bx r15 尝试使用 PEBS 记录记录其他 CPU 寄存器信息 但是我如何从 perf data 查看这些信息 原来的命令是perf report 并且只显
  • 记一次性能优化,单台4核8G机器支撑5万QPS!

    前言 这篇文章的主题是记录一次Python程序的性能优化 在优化的过程中遇到的问题 以及如何去解决的 为大家提供一个优化的思路 首先要声明的一点是 我的方式不是唯一的 大家在性能优化之路上遇到的问题都绝对不止一个解决方案 如何优化 首先大家
  • 多线程编程与性能优化

    引言 在上一篇的入门篇中 我们对Android线程的基础概念和多线程编程模型有了初步了解 本篇将深入探讨多线程编程技术和性能优化策略 以提升应用的效率和响应性 高级多线程编程技术 使用线程池管理线程 线程池是一组预先创建的线程 用于执行任务
  • 黑马React:基础拓展

    黑马React D10 基础拓展 Date December 18 2023 useReducer 基础使用 作用 让 React 管理多个 相对关联 的状态数据 补充 和useState的作用类似 用来管理相对复杂的状态数据 特点 use
  • React Jsx转换成真实DOM过程?

    面试官 说说React Jsx转换成真实DOM过程 一 是什么 react 通过将组件编写的 JSX 映射到屏幕 以及组件中的状态发生了变化之后 React 会将这些 变化 更新到屏幕上 在前面文章了解中 JSX 通过 babel 最终转化
  • perf stat 输出的解释

    我开发了一个代码 可以输入大的二维图像 高达 64MPixels 并且 对每一行应用过滤器 转置图像 使用阻塞以避免大量缓存未命中 对图像的列 当前行 应用过滤器 将过滤后的图像转回以进行其他计算 虽然它没有改变任何东西 但为了我的问题的完
  • 为什么 perf stat 将“stalled-cycles-backend”显示为<不支持>?

    Running perf stat ls显示这个 Performance counter stats for ls 1 388670 task clock 0 067 CPUs utilized 2 context switches 0 0
  • Linux中通过perf为未列出的函数添加动态跟踪点

    我正在尝试跟踪功能zap pte range来自 mm memory c 使用perf 但功能并未在其中列出perf probe F 那么有没有办法动态追踪这个函数呢 IE 显式添加跟踪点并重新编译内核 perf probe a zap p
  • Golang拼接字符串性能对比

    g o l a n g golang g o l an g
  • PERF_TYPE_HARDWARE 和 PERF_TYPE_HW_CACHE 并发监控

    我正在研究一个自定义实现perf event open系统调用 该实施旨在支持各种PERF TYPE HARDWARE PERF TYPE SOFTWARE and PERF TYPE HW CACHE活动为任何核心上的特定线程 In 英特
  • 从 perf 获取用户空间堆栈信息

    我目前正在尝试在我正在测试的 PostgreSQL 版本中追踪一些幻像 I O 它是一个多进程服务器 将磁盘 I O 关联回特定后端和查询并不简单 我还以为Linux的perf工具将是理想的选择 但我正在努力捕获块 I O 性能计数器指标并
  • 有没有办法使用 perf 工具查找流程中各个功能的性能?

    我正在尝试在流程中实现各个功能的性能 我该如何使用 perf 工具来做到这一点 还有其他工具吗 例如 假设 main 函数调用函数 A B C 我想分别获得主要功能以及功能 A B C 的性能 有没有一个很好的文档来了解 perf 源代码
  • perf 找不到外部模块符号

    跑步时perf它找到了我的程序的内核符号和符号 但没有找到外部模块符号 我已经编写了一个内核模块 我使用它加载insmod我怎么知道perf也找到它的符号 我正在运行 2 6 37 6 内核 无法升级 我的perf尚不支持矮人选项 但我认为
  • “perf record”或“perf-record”可以对子进程进行采样吗?

    假设我有一个harness二进制文件 它可以根据命令行选项生成不同的基准 我对这些基准测试非常感兴趣 我有3个选择 更改线束二进制文件以生成perf record运行基准测试并进行采样的子进程 just do perf record har
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • 性能统计与性能记录

    我对之间的区别感到困惑perf record and perf stat当涉及到对页面错误 缓存未命中以及其他任何事件进行计数时perf list 我在下面有两个问题 问题 1 的答案可能也有助于回答 问题 2 但我明确地写出了它们 以防它
  • 无法使用 linux perf 对硬件缓存事件进行采样

    由于某种原因 我无法采样 perf record 硬件缓存事件 perf record e L1 dcache stores a c 100 sleep 5 perf record Woken up 1 times to write dat
  • 如何使用 python 子进程杀死性能记录?

    我正在尝试使用性能实用程序 https www brendangregg com perf html监视我的系统 它将在 python 脚本中启动和终止 我创建了一个沙箱 如下所示 extra params F 99 g a record

随机推荐

  • 解决文字和elementUI中的进度条progress组件不能在同一行的问题

    我们使用span标签包裹一段文字 想要和elementUI中的progress组件显示在同一行 效果如下 span是一个行元素 progress是一个块元素 起初我是使用弹性盒布局 display flex 想让他们显示在一行 但是使用弹性
  • df查询命令用法区别。df -ih与df -lh

    今天磁盘显示没有可用空间了 google后记录一下 本人是菜鸟一枚 搞不清楚 i 与 h的区别 幸好文章地址http www 111cn net sys CentOS 86335 htm 截图如下 经过对比发现假如执行df lh命令发现磁盘
  • 基于ADRC的FOC位置环控制

    ADRC位置环控制 ADRC介绍 1 非线性跟踪微分器 2 非线性ESO观测器 3 非线性状态误差反馈控制律原理 NLSEF 4 调参流程 1 调TD 2 调ESO 3 调NLSEF 5 基于ADRC的位置环设计 ADRC框图 基于ADRC
  • PKG_CHECK_MODULES未定义

    一直以来 对于使用automake有点害怕 网上的大多资料都是说明autoconf生成什么文件 automake又做什么事情 还有autoscan等等 笔者在使用开源项目过程中遇到了一个问题 PKG CHECK MODULES未定义 奇怪
  • python turtle画表情包--不可以色色

    闲来无事 翻到以前的一个代码 将它魔改一下 不可以色色 先看看运行结果图 代码如下 小伙伴们可以根据自己的需要进行更改 import turtle as t if name main t speed 0 t penup t right 30
  • 机器学习-支持向量机(非线性分类)

    一 介绍 在进行分类的时候 大部分数据并不是线性可分的 而是需要通过数据映射 将数据变换到高维度进行分类 这就需要借助核函数来对其进行变换 我们已经在线性情况下 超平面公式可以写为 对于线性不可分 我们使用一个非线性映射 将数据映射到特征空
  • css3直线运动_纯css3动画--边框线条动画

    这是一款使用纯CSS3制作的效果非常炫酷的元素边框线条动画特效 这个元素边框线条动画使用伪元素和keyframes来制作线条运动效果 制作方法 1 HTML结构 该边框线条动画特效的HTML结构使用的是一个空的 来作为容器 2 CSS样式
  • 后缀名为.phps的文件

    文章目录 前言 一 phps是什么 二 使用情场景 三 其他使用场景 前言 遇到名为index phps的文件 不明白 phps代表什么意思 这里记录一下 一 phps是什么 phps即为 PHP Source PHP Source 由 T
  • DCDC基础(3)--BUCK电路的电感选型

    最近开通了公众号 射频工程师的日常 有文章更新 可以关注一下 谢谢 上一节带大家了解了一下BUCK电路的反馈电阻和自举电容的问题 从原理上分析了下组成BUCK电路的各个元器件的作用 又有人问了 面试中经常被问到BUCK的功率电感怎么选型 电
  • 多线程基础

    文章目录 1 线程简介 1 1 多任务 1 2 多线程 1 2 1 普通方法调用和多线程 1 3 程序 进程 线程 1 3 1 Process与Thread 1 4 核心概念 2 线程实现 2 1 三种创建方式 2 1 1 Thread 2
  • 阿里的easyExcel导出

    easyExcel的gitHub地址 https github com alibaba easyexcel 开发环境 springboot 1 导入依赖
  • 如何在thinkphp5.1中写接口及接口调用

    在thinkphp5 1中如何写接口及如何调用接口 对于php不熟悉的人来说 解除thinkphp还是挺有难度的 下面记录如何编写接口 及如何对编写的接口进行调用 1 首先在thinkphp中的application中的api contro
  • 毕业设计-基于深度学习的安全帽智能识别系统

    目录 前言 课题背景和意义 实现技术思路 一 系统架构 二 基于深度学习的目标检测算法实现 三 交互设计与实现 四 基于深度学习的安全帽智能识别系统测试 五 总结 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或
  • SecureCRT 访问Linux虚拟机(Oracle VM VirtualBox) 返回超时密码错误 解决办法

    问题描述 虚拟机ip能ping通 SecureCRT就是链接不上 解决办法 在找了网上无数多的办法 并没有成功 ssh重启 修改权限 1 设置Oracle VM VirtualBox网络方式 2 进入系统检查ssh 转载 http blog
  • 分享一个python基于数据可视化的智慧社区服务平台源码

    作者 计算机源码社 个人简介 本人七年开发经验 擅长Java Python PHP NET Node js 微信小程序 爬虫 大数据等 大家有这一块的问题可以一起交流 学习资料 程序开发 技术解答 文档报告 JavaWeb项目 微信小程序项
  • 【华为OD机试真题 JAVA】两数之和绝对值最小

    JS版 华为OD机试真题 JS 两数之和绝对值最小 标题 两数之和绝对值最小 时间限制 1秒 内存限制 32768K 语言限制 不限 给定一个从小到大的有序整数序列 存在正整数和负整数 数组 nums 请你在该数组中找出两个数 其和的绝对值
  • CSAPP第二章课后作业题

    include
  • 2020最新字节跳动面试经验分享,已拿到offer (4轮技术面+hr面)

    随着秋招的开启 不管是应届毕业生找工作 还是在职程序员跳槽去找更高薪水的工作 都要面临面试这一难关 应对面试不仅需要丰富的项目经历 还需要牢固的基础知识 在这里 跟大家分享一下我面试字节跳动的经验 包括4轮技术面 hr面 希望对大家有帮助
  • STM32 软件仿真失败 ***** error 65: access violation at 0x40021000 : no ****'read' permission******

    在使用STM32进行软件仿真时 可能会遇到很多问题 最常见的当然如标题所示 STM32 软件仿真失败 no read permission 还有其他很多问题比如 error 35 undefined line number BS Templ
  • react性能优化

    写在前面的话 要想解决问题 首先得找到问题的根源 所以 说起性能分析 还是要从其生命周期和渲染机制说起 1 渲染机制 react的组件渲染分为初始化渲染和更新渲染 在初始化渲染的时候会调用根组件下的所有组件的render方法进行渲染 但是当