在url后加 ?react_pref 可以结合Chrome自带的Performance做性能测试

单组件优化:

核心:减少render函数执行次数

事件绑定:

  • 在constructor中使用bind绑定:

    1
    2
    3
    4
    constructor(props) {
    super(props)
    this.eventHandle = this.eventHandle.bind(this)
    }
    • 优点:只需要绑定一次,并且只会执行一次;
    • 缺点:即使不需要state也需要添加constructor来绑定,代码量多一点
  • 在render中使用bind绑定:

    1
    2
    3
    4
    5
    6
    7
    // ...
    render() {
    return (
    <button onClick={this.clickHandle.bind(this)}></button>
    )
    }
    // ...
    • 优点:写法简单;
    • 缺点:每次执行render都会重新执行一次,多次使用同一个函数需要绑定多次(不推荐使用该方法)
  • 在render中使用箭头函数绑定:

    1
    2
    3
    4
    5
    6
    7
    // ...
    render() {
    return (
    <button onClick={() => this.clickHandle()}></button>
    )
    }
    // ...
    • 优点:写法简单,相对于上一种方法性能稍好一点;
    • 缺点:每次执行render都要重新生成一个函数
  • 在函数初始化时使用箭头函数绑定(实验性):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // ...
    clickHandle = () => {
    // ...
    }
    render() {
    return (
    <button onClick={this.clickHandle}></button>
    )
    }
    // ...
    • 优点:写法简单,结合了以上三种方法的优点;
    • 缺点:目前是实验性的语法,需要babel转译

总结:方式一是官方推荐的方式,也是性能最好的方式;方法二和方法三有性能问题,并且当方法作为属性传递给子组件时会触发re-render,因为子组件的props发生了改变;方法四是最好的绑定方式,但是需要结合babel转译

属性传递:

由于js的特性(对象在内存中的存储),如果传递的是一个对象,尽量提前声明一个索引指向该对象,避免每次render都重新在内存中生成一个新的对象。

多组件优化:

核心:减少子组件render函数的执行次数(减少子组件的重渲)

定制子组件的shouldComponentUpdate

当父组件发生了render,子组件都会重新渲染。很多时候子组件并没有发生任何改变,它接收到父组件传给它的props并没有发生变化,自身的state也没有变化,这种情况下子组件的无脑重新render就可以在其shouldComponentUpdate()钩子函数里做一些操作。这个钩子函数默认返回true,即render会执行;我们在里面做些业务上的检测,再返回true或false来确定子组件该不该重新渲染。

使用React.PureComponent([email protected]新增)

它类似于React.Component,区别在于PurComponent简单的实现了shouldComponentUpdate()而Component没有实现。适用情况:组件的render函数在给定相同的props和state时渲染相同的结果(纯组件),可以提升性能。

Note(官网上的Note)
React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.
Furthermore, React.PureComponent’s shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also “pure”.

PureComponent的shouldComponent()只实现了浅对比,深对比太消耗性能(对象的深比较需要用到递归,复杂度太高,性能消耗太大)。

可以使用immutable这个库来进行对象的深比较,复杂度比较低,但是这个库比较大。使用方法参考文档

redux优化

当我们页面使用的数据需要对获取的redux中的数据进行一些处理(复杂的计算)才能使用,并且很多状态是经常切换得时候,我们可以将那些状态缓存起来,避免每次切换都重新计算。可以使用react官方推荐一个库——reselect,使用方法参考文档

列表类组件优化

当我们渲染一个列表时,必须给每一项传key,否则react会报一个警告。这个key不建议使用数组遍历时的index,因为它只能帮助我们消除警告而已,并没有任何实际意义。如果我们在数组前面添加一个元素,那么react会认为所有的元素都发生了改变,所以全部都重新渲染了,我们并没有感受到虚拟DOM带给我们的优化。所以key的值必须是唯一的才有意义。



推荐阅读
react组件性能优化探索实践
高性能 React 组件