React源码学习笔记 PureComponent

578 阅读1分钟

React源码学习笔记 PureComponent

  • 查看react源码,在ReactBaseClasses.js中找到PureComponent

    function PureComponent(props, context, updater) {
      this.props = props;
      this.context = context;
      this.refs = emptyObject;
      this.updater = updater || ReactNoopUpdateQueue;
    }
    const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
    pureComponentPrototype.constructor = PureComponent;
    Object.assign(pureComponentPrototype, Component.prototype);
    pureComponentPrototype.isPureReactComponent = true;
    

    说明PureComponent和Component唯一的区别是多了一个静态变量isPureReactComponent

  • 接着搜索isPureReactComponent,在ReactFiberClassComponent.js中找到

    if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    return (
      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
    );
    }
    

    说明PureComponent在更新时,会进行浅比较props和states

  • 核心代码shallowEqual,是一个对象浅比较的方法

    function shallowEqual(objA: mixed, objB: mixed): boolean {
      // 判断是否相等
      if (is(objA, objB)) {
        return true;
      }
    
      // 不是对象直接返回fasle
      if (
        typeof objA !== 'object' ||
        objA === null ||
        typeof objB !== 'object' ||
        objB === null
      ) {
        return false;
      }
    
      const keysA = Object.keys(objA);
      const keysB = Object.keys(objB);
      
      // 先比较长度
      if (keysA.length !== keysB.length) {
        return false;
      }
      
      // 再比较值
      for (let i = 0; i < keysA.length; i++) {
        if (
          !hasOwnProperty.call(objB, keysA[i]) ||
          !is(objA[keysA[i]], objB[keysA[i]])
        ) {
          return false;
        }
      }
    
      return true;
    }
    
  • 注意事项

    function checkShouldComponentUpdate(
      workInProgress,
      ctor,
      oldProps,
      newProps,
      oldState,
      newState,
      nextContext,
    ) {
      const instance = workInProgress.stateNode;
      if (typeof instance.shouldComponentUpdate === 'function') {
        let shouldUpdate = instance.shouldComponentUpdate(
          newProps,
          newState,
          nextContext,
        );
        return shouldUpdate;
      }
    
      if (ctor.prototype && ctor.prototype.isPureReactComponent) {
        return (
          !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
        );
      }
    
      return true;
    }
    

    说明可以通过shouldComponentUpdate覆盖自带的浅比较。