React知识整理-性能优化之pureComponent和memo

1/12/2020 React

react从入门到放弃

# React.PureComponent

  • React.PureComponent 与 React.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。
  • 如果赋予 React 组件相同的 props 和 state,render() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent 可提高性能。

注意:React.PureComponent中的 shouldComponentUpdate()仅对对象浅拷贝做比较。如果对象包含复杂的数据结构,可能无法检查出深层的差别,产生错误的对比。
仅仅在props和state较为简单是使用,或者深层数据结构发生变化调用forceUpdate()确保组件被正确更新。也可以考虑 immutable对象 (opens new window)加速嵌套数据的比较。

简单实现

// PureComponent.js
import React, { Component } from 'react'
export default class PureComponent extends Component {
  isPureComponent = true
  //传入新的属性对象和状态对象,然后返回一个是否需要更新的boolean值
  shouldComponentUpdate(nextProps,nextState){
     // 判断 只要有一个不相等性返回true更新。否则false不更新
     return !shallowEqual(this.props,nextProps)||!shallowEqual(this.state,nextState);
  }
}
// 浅比较 性格高 
// 比较obj1和obj2是否相等,如果相等的话则返回true,不相等返回false,只比较第一层
function shallowEqual(obj1,obj2){
  if(obj1 === obj2){
    return true;
  }
  if(typeof obj1 !='object' || obj1 === null ||typeof obj2 !='object' || obj2 === null){
    return false;
  }
  let keys1 = Object.keys(obj1);
  let keys2 = Object.keys(obj2);
  if(keys1.length != keys2.length){
    return false;
  }
  for(let key of keys1){
      if(!obj2.hasOwnProperty(key) || obj1[key]!=obj2[key]){
        return false;
      }
      /* if(obj2.hasOwnProperty(key)){
          if(obj1[key] != obj2[key]){
            if(typeof obj1[key] == 'object' && typeof obj2[key] == 'object'){
                return shallowEqual(obj1[key],obj2[key]);
            }
          }
      }else{
          return false;
      } */
  }
  return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# React.memo

const MyComponent = React.memo(function MyComponent(props) {
  /* 使用 props 渲染 */
});
1
2
3

React.memo为高阶组件。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class 组件。

如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。

  • 浅比较:默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现
    function MyComponent(props) {
    /* 使用 props 渲染 */
    }
    function areEqual(prevProps, nextProps) {
    /*
    如果把 nextProps 传入 render 方法的返回结果与
    将 prevProps 传入 render 方法的返回结果一致则返回 true,
    否则返回 false
    */
    }
    export default React.memo(MyComponent, areEqual);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • 此方法仅作为性能优化 (opens new window)的方式而存在。但请不要依赖它来“阻止”渲染,因为这会产生 bug。

简单实现:

function memo(FuncComponent,fn){
  shouldComponentUpdate(nextProps,nextState){
      return  fn?fn():true
  }
  return class  extends PureComponent{
      render(){
          return <FuncComponent {...this.props}/>
      }
  }
}
1
2
3
4
5
6
7
8
9
10
Last Updated: 1/13/2020, 7:38:12 AM
    asphyxia
    逆时针向