React 性能调优总结

首先要说一个库: why-did-you-update, 地址:why-did-you-update, 利用这个库可以在页面上快速看到多余渲染的问题:

因为多数情况下我们在React组件当中是不会去写shouldComponentUpdate这个hook来避免多余渲染的,所以就造成了少量的性能浪费。虽然优化是个漫长的道路,过早优化是邪恶的,但做还是要去做的。

下面讲一下基本的一些手段

shouldComponentUpdate

在React当中,每一次的setState操作,都会让Virtual DOM去做diff操作,虽然虚拟DOM的计算很快,但是随着组件越来越多,结构越来越复杂,当你改变某个简单的state时,就会造成连带很多Component的重新render,所以我们可以在组件内部去添加shouldComponentUpdate钩子来告诉React是否要更新组件

PureComponent

当然我们在实际开发过程当中,由于数据的复杂程度来说,基本是不会去写shouldComponentUpdatehook,这时就可以去使用PureComponent类来声明组件。

PureComponent的前身是PureRenderMixin,和Component的区别就在于组件在render之前会自动执行一次shallowEqual(浅比较),就相当于组件的第一层props和state的数据如果没有发生改变,render就不会去执行,从而减少了不必要的渲染。

根据React源码,如果组件是纯组件(Pure Component),那么一下比较是很容易理解的:

if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState);
}

为什么说是浅比较呢?这个很好理解,js的引用数据类型就很好的说明了这一点:

{} === {} //false
[] === [] //false

当然,你也可以在shouldComponentUpdate中自己来写深比较,在数据结构相对简单的情况下:

shouldComponentUpdate(nextProps, nextState) {
return nextProps.user.id === props.user.id;
}

如果是在PureComponent当中写了这个钩子,那么它就会被优先执行。

当然,在数据结构和嵌套比较深的情况下,这个方案也就不太管用了,所以,我们在前期定义数据结构时也是一个很重要的环节,可以去避免不必要的渲染。

Immutable or Immer

Facebook在2014年就推出了这个库: Immutable.js,用来使数据持久化。在数据创建后,就不得去改变,任何的增删改操作都是true一个新的Immutable对象:

import { Map } from "immutable";
const map1 = Map({ a: { aa: 1 }, b: 2, c: 3 });
const map2 = map1.set('b', 50);
map1 !== map2; // true
map1.get('b'); // 2
map2.get('b'); // 50
map1.get('a') === map2.get('a'); // true

ImmutableJS 最大的两个特性就是: immutable data structures(持久性数据结构)与 structural sharing(结构共享),持久性数据结构保证数据一旦创建就不能修改,使用旧数据创建新数据时,旧数据也不会改变,不会像原生 js 那样新数据的操作会影响旧数据。而结构共享是指没有改变的数据共用一个引用,这样既减少了深拷贝的性能消耗,也减少了内存。比如下图:

ImmutableJS的API过于复杂,而且我也没有用redux,而是采用了MutableMobx,看见Mobx的作者写了一个库Immer,相对于ImmutableJS 比较简单:

import produce from "immer"
/** * Classic React.setState with a deep merge */
onBirthDayClick1 = () => {
this.setState(prevState => ({
user: {
...prevState.user,
age: prevState.user.age + 1
}
}))
} /** * ...But, since setState accepts functions, * we can just create a curried producer and further simplify! */
onBirthDayClick2 = () => {
this.setState(
produce(draft => {
draft.user.age += 1
})
)
}

代码上的优化

少用bind

每次bind都会返回一个新函数,重复创建静态函数会浪费性能。最好直接使用箭头函数绑定或者利用闭包直接把处理函数传入子组件

setState优化

在我们去setState时,最好用新值去覆盖旧值,而不是修改原值。 对于数组,我们采用es6的spread语法:

this.setState(prevState => ({
words: [...prevState.words, 'marklar'],
}));

对于对象,我们采用Object.assign或spread:

    this.setState({
a: Object.assign({}, this.state.a, {b: '2222'})
})
//或者
this.setState({
a: {...this.state.a, {b: '222'}}
})

不要在PureComponent组件的props使用直接赋值的方式

style={ { width: '100px' } } 这样的做法传入组件会造成重复渲染

这样的方式会使shallowEqual一定返回false

正确的方式:

const YourStyle = { width: '100px' } 

return (
<YourComponent style={YourStyle}></YourComponent>
)

或者我们直接就用上面说到的Immutable.js 或者 Immer.js 来处理

React 性能调优总结的更多相关文章

  1. React 性能调优原理

    一.React影响性能的两个地方 二.调优原理

  2. React 性能调优记录(下篇),如何写高性能的代码

    react性能非常重要,性能优化可以说是衡量一个react程序员水平的重要标准. 减少你的渲染 这个大家都明白,只要是父组件中用了子组件,子组件就算没用prop也会进行依次渲染, 可以用pureCom ...

  3. React如何性能调优

    一. 二.调优例子 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=&q ...

  4. 小程序组件化框架 WePY 在性能调优上做出的探究

    作者:龚澄 导语 性能调优是一个亘古不变的话题,无论是在传统H5上还是小程序中.因为实现机制不同,可能导致传统H5中的某些优化方式在小程序上并不适用.因此必须另开辟蹊径找出适合小程序的调估方式. 本文 ...

  5. web前端性能调优

    最近2个月一直在做手机端和电视端开发,开发的过程遇到过各种坑.弄到快元旦了,终于把上线了.2个月干下来满满的的辛苦,没有那么忙了自己准备把前端的性能调优总结以下,以方便以后自己再次使用到的时候得于得心 ...

  6. [网站性能2]Asp.net平台下网站性能调优的实战方案

    文章来源:http://www.cnblogs.com/dingjie08/archive/2009/11/10/1599929.html 前言    最近帮朋友运营的平台进行了性能调优,效果还不错, ...

  7. Asp.net平台下网站性能调优的实战方案(转)

    转载地址:http://www.cnblogs.com/chenkai/archive/2009/11/07/1597795.html 前言 最近帮朋友运营的平台进行了性能调优,效果还不错,所以写出来 ...

  8. 第0/24周 SQL Server 性能调优培训引言

    大家好,这是我在博客园写的第一篇博文,之所以要开这个博客,是我对MS SQL技术学习的一个兴趣记录. 作为计算机专业毕业的人,自己对技术的掌握总是觉得很肤浅,博而不专,到现在我才发现自己的兴趣所在,于 ...

  9. sqlserver性能调优第一步

    相信不少的朋友,无论是做开发.架构的,还是DBA等,都经常听说“调优”这个词.说起“调优”,可能会让很多技术人员心头激情澎湃,也可能会让很多人感觉苦恼,不知道如何入手.当然,也有很多人对此不屑一顾,因 ...

随机推荐

  1. json文件读写函数

    老师代码: import json def op_data(filename,dic=None): if dic:#写入进去 with open(filename,'w',encoding='utf- ...

  2. bootstrap常见的面试题

    1.  如果让一个元素在pc端显示而在手机端隐藏,下列选项正确的是(b). A. visible-xs-8  hidden-md B. visible-md-8 hidden-xs C. visibl ...

  3. JAVA自学笔记19

    JAVA自学笔记19 1.集合总结 Collection(单列集合) List(有序可重复) ArrayList:底层数据结构是数组 ,查询快,增删慢.线程不安全,效率高 Vector:底层数据结构是 ...

  4. 问题9:tabtle 整理

    合并“行”单元格: <th colspan="2">Telephone</th> 合并“列”单元格: <th rowspan="2" ...

  5. dubbo+zipkin调用链监控(二)

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  6. VB编写的程序加入防火墙的例外中

    在工程中要先引入: NetCon 1.0 Type Library NetFwTypeLib Option Explicit Const NET_FW_SCOPE_ALL = 0 Const NET_ ...

  7. Java全栈程序员之09:IDEA+GitHub

    GitHub是源码托管站点,其依赖于Git这个源码管理工具来进行代码的托管.所以将我们的代码托管到GitHub之前,我们需要安装Git. 1.Git安装 可以通过输入git命令来确定是否在本机已经安装 ...

  8. 使用sshfs将远程目录挂载到本地

    使用sshfs将远程目录挂载到本地 转自:http://blog.sina.com.cn/s/blog_6561ca8c0102vc2u.html 在Linux下我们通常使用ssh命令来登录远程Lin ...

  9. Python的pandas

    pandas 是python中很重要的组件,网上关于pandas 的文章也很多,比如Python科学计算之Pandas 和 Python数据分析入门 Pandas基于两种数据类型:series与dat ...

  10. PowerShe 消息提示框测试

    1. 使用powerShell 弹出一个简单的消息框,代码如下,创建test.ps1脚本文件. $ConfirmPreference = 'None' $ws = New-Object -ComObj ...