前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React源码解析之PureComponet的浅比较

React源码解析之PureComponet的浅比较

作者头像
进击的小进进
发布2020-02-13 10:37:42
5010
发布2020-02-13 10:37:42
举报

前言:React源码解析之updateClassComponent(下) 中提到了PureComponent的浅比较:

代码语言:javascript
复制
//如果是纯组件的话,用**浅比较**来比较 props/state
  if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    return (
      //浅等于的判断
      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
    );
  }

接下来就看下shallowEqual()的源码

一、shallowEqual 作用: PureComponet做浅比较的核心function

源码:

代码语言:javascript
复制
import is from './objectIs';

const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * Performs equality by iterating through keys on an object and returning false
 * when any key has values which are not strictly equal between the arguments.
 * Returns true when the values of all keys are strictly equal.
 */
//true 为不要更新
//false 为要更新
function shallowEqual(objA: mixed, objB: mixed): boolean {
  //同 Object.js()
  //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description
  //不要更新
  if (is(objA, objB)) {
    return true;
  }
  //只要有一个不是 object或为 null 则返回 false,要更新
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);
  //两个 object 的key 数不一样,则返回 false,要更新
  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  //每一个 value 去一一比较是否是浅相等
  //能执行到这里,说明两者 key 的长度是相等的
  for (let i = 0; i < keysA.length; i++) {
    if (
      //不通过原型链查找是否有自己的属性
      !hasOwnProperty.call(objB, keysA[i]) ||
      //判断两值是否相等
      !is(objA[keysA[i]], objB[keysA[i]])
    ) {
      //只要没有属性/两个value不等,则返回 false,需要更新
      return false;
    }
  }
  //默认返回 true,不需要更新
  return true;
}

export default shallowEqual;

解析: (1) 关于PureComponetComponent的区别,请看: https://zh-hans.reactjs.org/docs/react-api.html#reactpurecomponent

(2) is()Object.is(),React 直接将其 实现在代码内部了:

代码语言:javascript
复制
/**
 * inlined Object.is polyfill to avoid requiring consumers ship their own
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
function is(x: any, y: any) {
  return (
    (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
  );
}

export default is;

关于Object.is()的作用及用法,请看: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/is

(3) 注意下返回的true/false 因为是 return !shallowEqual(),所以true 表示不更新,false表示要更新

(4) 主要分四种情况 ① 非对象类型的比较,直接使用is(objA, objB)判断

② 到 ④ 是对象类型的比较

objA/objB中,只要有一个不是object或为null则返回falseobjA/objBkeyLength不一样,则返回false,此举的目的是简单比较,优化性能 ④ 循环比较objA/objB的每一个value,判断是否浅相等

针对 ④ 的例子: 对象的value是非对象类型:

代码语言:javascript
复制
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是对象类型:

代码语言:javascript
复制
  const a={c:{e:3},d:2}
  const b={c:{e:3},d:2}

  hasOwnProperty.call(b, 'c') //true
  //可以看到,只能用于浅比较
  Object.is(a['c'], b['c']) //false

可以看到,Object.is()PureComponet做浅比较的根本函数。

GitHub: https://github.com/AttackXiaoJinJin/reactExplain/blob/master/react16.8.6/packages/shared/shallowEqual.js


(完)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 webchen 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档