zoukankan      html  css  js  c++  java
  • Component、PureComponent源码解析

    1.什么是Component,PureComponent?

    都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nextProps,nextState)方法,通过浅比较(比较一层),来判断是否需要重新render()函数,如果外面传入的props或者是state没有变化,则不会重新渲染,省去虚拟dom的生成和对比过程,从而提高性能。

    2.PureComponent应用

    一般用于纯函数

    3.Component源码分析

       /*
          Component 基类
          1.设置react的props,content,refs,updater等属性
          2.要知道class继承是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this
    class A extends React.Component{construcroe(){props){super(props)}} */ function Component(props, context, updater) { this.props = props;//父子传递数据 this.context = context;//爷孙传递数据 this.refs = emptyObject; //子到父传递数据 this.updater = updater || ReactNoopUpdateQueue; //更新数据 } Component.prototype.isReactComponent = {};//给Component原型上添加属性 /* 使用setState来改变Component类内部的变量 enqueueSetState调用这个方法实现更新机制 partialState:要更新的state,可以是object/function */ Component.prototype.setState = function (partialState, callback) {//给Component原型上添加方法 //判断setState中的partialState是否符合条件 如果不符合 则抛出错误 if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) { { throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables."); } } //state的更新机制 在react-dom中实现 不同平台更新内容可能不同 this.updater.enqueueSetState(this, partialState, callback, 'setState'); }; //在Component的深层次改变但是没有调用setState时 调用此方法 强制更新一次 Component.prototype.forceUpdate = function (callback) { this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); };
    4.PureComponent源码解析
      function ComponentDummy() { }
        // ComponentDummy的原型继承Component的原型 
        ComponentDummy.prototype = Component.prototype;
    
        function PureComponent(props, context, updater) {//构造函数属性(实例属性),会被实例共享,但不会被修改
          this.props = props;
          this.context = context;
          this.refs = emptyObject;
          this.updater = updater || ReactNoopUpdateQueue;
        }
        //不能直接继承Component 因为如果是直接继承Component 还会继承它的Constructor方法 目的:减少一些内存使用
        var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
        //实例沿着原型链向上查询,只要是自己继承的,都被认作自己的构造函数
        pureComponentPrototype.constructor = PureComponent;
        //这里做了优化 把 Component.prototype属性浅拷贝到pureComponentPrototype上 防止原型连拉长 导致方法的多层寻找 减少查询次数 
        _assign(pureComponentPrototype, Component.prototype);
        //添加了这个isPureReactComponen参数 来判断是Component还是PureComponent组件
        pureComponentPrototype.isPureReactComponent = true;

    5.PureComponent如何实现是否需要更新,来提高性能?

    //这个变量用来控制组件是否需要更新 默认为true进行更新操作
    var shouldUpdate = true;
    // inst是组件实例 如果PureComponent定义有shouldComponentUpdate方法 则和Component基类一样 
    if (inst.shouldComponentUpdate) {
      shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
    } else {
      if (this._compositeType === CompositeType.PureClass) {
        // 用shallowEqual函数对比 props 和 state 的改动
        // 如果都没改变就不用更新
        shouldUpdate =
          !shallowEqual(prevProps, nextProps) ||
          !shallowEqual(inst.state, nextState);
      }
    }

      1.shallowEqual函数解析

    目的:比较值相等,或者对象含有相同的属性、且属性值是否相等

    function is(x, y) { //处理了基本类型的比较
      //1,针对+0===-0的情况
      //2. 针对NaN!==NanN的情况
      return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y 
      ;
    }
    var is$1 = typeof Object.is === 'function' ? Object.is : is;
    var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
    
    //返回值:false更新  true不更新
    function shallowEqual(objA, objB) {
      if (is$1(objA, objB)) {//基本数据类型 不更新
        return true;
      }
     //由于Object.is 可以对基本数据类型做一个精确的比较 如果不等只有一种情况 那就是object, objA/objB中,只要有一个不是object或为null则返回false
      if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
        return false;
      }
      //过滤掉基本数据类型 就是对象比较 首先比较长度 优化性能
     //比较oldProps和新的Props以及oldState和newState长度是否相同 如果长度不同则重新更新渲染 如果长度相同则不用重新渲染 如果不相等 不会往下执行 优化性能
      var keysA = Object.keys(objA);
      var keysB = Object.keys(objB);
      if (keysA.length !== keysB.length) {
        return false;  
      }
       //如果key相等
       //如果objA的属性不在objB里,或者是objA的属性值和objB的属性值不等 则重新渲染 不考虑当keysA[i]为对象的多层问题 浅显比较 提高性能
       for (var i = 0; i < keysA.length; i++) { 
           if (!hasOwnProperty$2.call(objB, keysA[i]) || !is$1(objA[keysA[i]], objB[keysA[i]])) {
          return false;
        }
      return true;
     }
    }



    1.理解:is()函数 x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y 解决了NaN不等于NaN的情况和-0===+0的情, 实现了Object.is
    +0 === -0 //true
    NaN === NaN // false
    Object.is(+0, -0) // false
    Object.is(NaN, NaN) // true


      2.Object.prototype.hasOwnProperty 用来判断某个属性是否是对象自身的属性 

      3.浅比较的使用

       对象的value是简单数据类型

    const a={c:1,d:2}
    const b={c:1,d:2}
    Object.is(a,b) //false
    hasOwnProperty.call(b, 'c') //true
    Object.is(a['c'], b['c']) //true

    对象的value有复杂数据类型

     const a={c:{e:3},d:2}
     const b={c:{e:3},d:2}
     hasOwnProperty.call(b, 'c') //true
     //可以看到,只能用于浅比较 这里会出现错误判定 从而重新更新render 
     Object.is(a['c'], b['c']) //false

     注意点:shouldComponentUpdate(nextProps,nextState)  返回false阻止更新 挂载阶段是不起作用的  更新阶段起作用 图如下

    
    
  • 相关阅读:
    Java集合中迭代器
    java 基础归纳总结(三)
    java 基础归纳总结(二)
    java 基础归纳总结(一)
    python之hashlib模块
    python之configparser模块
    Python之time模块
    python之os模块
    python之random模块
    python generator(生成器)
  • 原文地址:https://www.cnblogs.com/nimon-hugo/p/12561529.html
Copyright © 2011-2022 走看看