文章目录

  • React性能优化SCU
    • React更新机制
    • render函数被调用
    • PureComponent
    • 高阶组件memo

React性能优化SCU

React更新机制

我们在前面文章已经讲解过React的渲染流程:

那么React的更新流程呢?

React在props或state发生改变时,会调用React的render方法,会创建一颗不同的树。

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

如果一棵树参考另外一棵树进行完全比较更新,那么即使是最先进的算法,该算法的复杂程度为 O(n²),其中 n 是树中元素的数量;

https://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf;

如果在 React 中使用了该算法,那么展示 1000 个元素所需要执行的计算量将在百万的量级范围;

这个开销太过昂贵了,React的更新性能会变得非常低效;

于是,React对这个算法进行了优化,将其优化成了O(n),如何优化的呢?

同层节点之间相互比较,不会垮节点比较;

不同类型的节点,产生不同的树结构;

开发中,可以通过key来指定哪些节点在不同的渲染下保持稳定;

当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素:

将key为333的元素插入到最前面的位置即可;

在这种场景下,key为111和222的元素仅仅进行位移,不需要进行任何的修改;

key的注意事项:

key应该是唯一的;

key不要使用随机数(随机数在下一次render时,会重新生成一个数字);

使用index作为key,对性能是没有优化的;

render函数被调用

演示render函数调用我准备使用如下的组件嵌套关系

此时App中有两个数据, message和conter, 并且将message传给Home组件展示, 将conter传给About组件展示; 切App组件有两个按钮, 分别用于修改message和conter数据的, 代码如下

export class App extends Component {constructor() {super()this.state = {message: "Hello World",conter: 100}}changeText() {this.setState({message: "你好啊"})}changeNum() {this.setState({conter: this.state.conter + 1})}render() {console.log("App render")const { message, conter } = this.statereturn (<div><h2>{message}</h2><button onClick={() => this.changeText()}>修改文本</button><h2>{conter}</h2><button onClick={() => this.changeNum()}>修改数字</button><Home message={message}/><About conter={conter}/></div>)}
}

那么此时, 我们点击任意一个按钮, 修改了state中的数据, 就会重新调用App组件的render函数

而当App的render函数被调用时,所有的子组件的render函数都会被重新调用;

并且当我点了一次修改文本按钮时, state中的message已经变成了"你好啊", 当我再次点击修改文本按钮时, state中的message依然是"你好啊", 并没有发生变化, 但是App组件的render函数依然会重新执行, 并且它的子组件Home和About中的render函数也会重新执行

那么,我们可以思考一下,在以后的开发中,我们只要是修改了 App中的数据,所有的组件都需要重新render,进行diff算法,性能必然是很低的:

事实上,很多的组件没有必须要重新render;

它们调用render应该有一个前提,就是依赖的数据(state、props)发生改变时,再调用自己的render方法;

如何来控制render方法是否被调用呢?

前面我有讲到一个生命周期函数, 通过shouldComponentUpdate函数方法可以控制render方法是否被调用;

例如App组件中, 我们调用shouldComponentUpdate生命周期函数, 当message和conter改变时, 才会执行render函数, 否则不执行

shouldComponentUpdate(newProps, newState) {if (this.state.message !== newState.message || this.state.conter !== newState.conter) {return true}return false
}

我们同样可以在Home组件和About组件调用shouldComponentUpdate生命周期函数, 进行限制

// Home组件export class Home extends Component {shouldComponentUpdate(newProps, newState) {// 当message改变才会调用render函数if (this.props.message !== newProps.message) return truereturn false}render() {console.log("Home render")const { message } = this.propsreturn (<div><h2>{message}</h2></div>)}
}
// about组件export class About extends Component {shouldComponentUpdate(newProps, newState) {// 当conter改变才会调用render函数if (this.props.conter !== newProps.conter) return truereturn false}render() {const { conter } = this.propsconsole.log("About render")return (<div><h2>{conter}</h2></div>)}
}

此时在App组件中点击修改文本按钮, 由于message值发生变化, 只有App组件和Home组件的render函数会被重新调用, About组件不会; 点击修改数字按钮, App组件和About组件的render函数会被调用, Home组件不会, 这样我们就对性能进行了优化


PureComponent

如果所有的类,我们都需要向上面代码一样手动来实现 shouldComponentUpdate,那么会给我们开发者增加非常多的工作量, 况且上面代码中还只是修改了两个state中的数据, 如果数据更多我们的工作量将更大。

我们来设想一下shouldComponentUpdate中的各种判断的目的是什么?

props或者state中的数据是否发生了改变,来决定shouldComponentUpdate返回true或者false;

事实上React已经考虑到了这一点,所以React已经默认帮我们实现好了,如何实现呢?

将class继承自Component修改为PureComponent就可以了。

export class Home extends PureComponent {render() {const { message } = this.propsreturn (<div><h2>{message}</h2></div>)}
}

高阶组件memo

目前我们是针对类组件可以使用PureComponent,那么函数式组件呢?

事实上函数式组件我们在props没有改变时,也是不希望其重新渲染其DOM树结构的

针对于函数组件, 我们需要使用一个高阶组件memo:

使用memo对函数组件进行包裹, memo调用会返回一个新的组件, 返回这个组件后, 函数组件也会和累组件的PureComponent是一样的效果

// 导入memo
import { memo } from "react";// 使用memo会返回一个新的组件
const Profile = memo(function(props) {return (<div><h2>{props.message}</h2></div>)
})export default Profile

React性能优化SCU | PureComponent | memo相关推荐

  1. [react] 你知道的react性能优化有哪些方法?

    [react] 你知道的react性能优化有哪些方法? shouldComponentUpdate PureComponent :Class Component React.Memo :Functio ...

  2. React性能优化(完整版)

    我的博客 http://wangxince.site/my-demo-markdown/ React 性能优化 1.减少 render 次数 shouldComponentUpdate PureCom ...

  3. React性能优化记录(不定期更新)

    React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...

  4. Airbnb 爱彼迎房源详情页中的 React 性能优化

    Airbnb 爱彼迎工程师和数据科学家将定期和大家分享移动开发.系统架构.数据科学及人工智能等领域的技术探索和经验心得. 正文从这开始-- 在一些容易被忽视但又非常重要的场景,可能会有许多严重影响性能 ...

  5. react性能优化方案_React灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...

    react性能优化方案 在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑随着Node.js的 ...

  6. React 组件性能优化之 PureComponent 的使用

    文章出自个人博客:https://knightyun.github.io/2021/05/09/js-react-purecomponent,转载请申明 在 React 类组件中,如果状态(state ...

  7. React性能优化 PureComponent

    为什么使用? React15.3中新加了一个 PureComponent 类,顾名思义, pure 是纯的意思, PureComponent 也就是纯组件,取代其前身 PureRenderMixin  ...

  8. react性能优化之memo的作用和memo的坑

    前言 在react中,组件渲染的是最常有的事情.但是,有部分的渲染是不必要的,是可以避免的. 在react的一般规则中,只有父组件的某一个状态改变,父组件下面所有的子组件不论是否使用了该状态,都会进行 ...

  9. react 组件遍历】_从 Context 源码实现谈 React 性能优化

    (给前端大全加星标,提升前端技能) 转自:魔术师卡颂 学完这篇文章,你会收获: 了解Context的实现原理 源码层面掌握React组件的render时机,从而写出高性能的React组件 源码层面了解 ...

最新文章

  1. C++ Map用法详解
  2. python归并排序 分词_python-归并排序
  3. html基本标签与属性
  4. 是圆的问题呢(洛谷P1652题题解,Java语言描述)
  5. 使用glbindbuffers产生访问冲突_预防IP地址冲突的应对方案,你知道吗?
  6. c#中结构与类的区别(转)
  7. linux之systemctl命令
  8. ubuntu14.04-安装flash
  9. Linux设备驱动模型-Kobject
  10. zoj 3332 Strange Country II
  11. 如何做到在子线程更新 UI?
  12. PyTorch注意力机制【动手学深度学习v2】
  13. 计算机网络技术—知识点汇总
  14. 给编程入门者的唠叨话(全栈路线)
  15. BAT有增有减nbsp;互联网2015校园…
  16. Windows系统win10系统看图pdf阅读器软件推荐
  17. 安科瑞APM三相四线/IEC标准网络电力仪表的功能及应用
  18. 超详细宝塔面板搭建和安装wordpress网站图文教程(附案例)
  19. SGD,Adagrad,Adadelta,Adam等优化方法总结和比较
  20. 更新iOS 15失败, iPhone变成白苹果怎么办呢?

热门文章

  1. MySQL多表操作:建表与多表查询
  2. HDMI介绍及硬件实现原理
  3. 在Vue中调用微信的扫描二维码功能
  4. 笨蛋!连0.2这么简单的数字都搞不定!你被炒了!
  5. SEO网站优化基础解决方案[快速入门]
  6. Developing Large Web Applications
  7. jsp的文件操作(二)
  8. 金融工程---引论以及参考书目
  9. 开关电源模块并联供电系统_水冷风冷高频开关电源直流整流器
  10. A. Tom Riddle's Diary