React性能优化

Favori,

Performance

图:Kashish Arora

Code Splitting

可以帮你“懒加载”代码,如果你没办法直接减少应用的体积,那么不妨尝试把应用从单个 bundle 拆分成单个 bundle + 多份动态代码的形式。

解耦

组件尽可能的进行拆分、解耦

bind 函数优化

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      num:1,
      title:'react study'
    }
    this.handleClick = this.handleClick.bind(this);
    this.item = {react:'redux'};
  }
 
  handleClick(){
    this.setState({
      num: this.state.num + 1
    })
  }
 
  render(){
    return (
      <div className="App">
        <h2> {this.state.num} </h2>
        <button onClick={this.handleClick}>btn1</div>
        <button onClick={this.handleClick.bind(this)}>btn2</div>
        <button onClick={()=>this.handleClick()}>btn3</div>
      </div>
    )
  }
}

第一种是在构造函数中绑定 this,第二种是在 render()函数里面绑定 this,第三种就是使用箭头函数,都能实现上述方法;

但是哪一种方法的性能最好,是我们要考虑的问题。应该大家都知道答案:第一种的性能最好。

因为第一种,构造函数每一次渲染的时候只会执行一遍;

而第二种方法,在每次 render()的时候都会重新执行一遍函数;

第三种方法的话,每一次 render()的时候,都会生成一个新的箭头函数,即使两个箭头函数的内容是一样的。

第三种方法我们可以举一个例子,因为 react 判断是否需要进行 render 是浅层比较,简单来说就是通过===来判断的,如果 state 或者 prop 的类型是字符串或者数字,只要值相同,那么浅层比较就会认为其相同;

但是如果前者的类型是复杂的对象的时候,我们知道对象是引用类型,浅层比较只会认为这两个 prop 是不是同一个引用,如果不是,哪怕这两个对象中的内容完全一样,也会被认为是两个不同的 prop。

不要滥用 props

不要滥用 props,props 尽量只传需要的数据,避免多余的更新,尽量避免使用{…props}

动态导入

  import(``"./math"``).then(math => {
  console.log(math.add(16, 26));
  });

react-loadable

使用不可突变数据结构

使用Immutable对象

  • Map:键值对集合,对应Object,Es6种也有专门的Map对象
  • List:有序可重复列表,对应于Array
  • ArraySet:有序且不可重复的列表

使用Map生成一个immutable对象

import { Map , is } from 'immutable';
 
let obj = Map({
  'name': 'react study',
  'course': Map({name: 'react+redux'})
})
 
let obj1 = obj.set('name','darrell');
 
console.log(obj.get('course') === obj1.get('course')); // 返回true
console.log(obj === obj1); // 返回false

Immutable.is 比较的是两个对象的 hashCode 或 valueOf(对于 JavaScript 对象)。由于 immutable 内部使用了 Trie 数据结构来存储,只要两个对象的 hashCode 相等,值就是一样的。这样的算法避免了深度遍历比较,性能非常好。

let obj = Map({name:1,title:'react'});
let obj1 = Map({name:1,title:'react'});
console.log(is(obj,obj1)); // 返回true
 
let obj2 = {name:1,title:'react'};
let obj3 = {name:1,title:'react'};
console.log(is(obj2,obj3)); // 返回false

Immutable优点:

  • 减少内存的使用
  • 并发安全
  • 降低项目的复杂度
  • 便于比较复杂数据,定制shouldComponentUpdate方便
  • 时间旅行功能
  • 函数式编程

Immutable缺点:

  • 学习成本
  • 库的大小(建议使用seamless-immutable)
  • 对现有项目入侵严重
  • 容易与原生的对象进行混淆

减少重复渲染

如果是类组件,使用shouldComponentUpdate减少重新渲染,如果是函数组件,要写清楚依赖项数组

减少dom结构更改

如果要操作Vitural Dom,尽量减少dom结构更改

key的优化

列表要声明key

虚拟列表

大数据量的列表需要使用虚拟滚动列表 见 react virtualList 虚拟列表无限滚动实现