1.什么是Component,PureComponent?

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

2.PureComponent应用

一般用于纯函数

3.Component源码分析

  1. /*
  2. Component 基类
  3. 1.设置react的props,content,refs,updater等属性
  4. 2.要知道class继承是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this
    class A extends React.Component{construcroe(){props){super(props)}}
  5. */
  6. function Component(props, context, updater) {
  7. this.props = props;//父子传递数据
  8. this.context = context;//爷孙传递数据
  9. this.refs = emptyObject; //子到父传递数据
  10. this.updater = updater || ReactNoopUpdateQueue; //更新数据
  11. }
  12. Component.prototype.isReactComponent = {};//给Component原型上添加属性
  13. /*
  14. 使用setState来改变Component类内部的变量 enqueueSetState调用这个方法实现更新机制
  15. partialState:要更新的state,可以是object/function
  16. */
  17. Component.prototype.setState = function (partialState, callback) {//给Component原型上添加方法
  18. //判断setState中的partialState是否符合条件 如果不符合 则抛出错误
  19. if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) {
  20. {
  21. throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");
  22. }
  23. }
  24. //state的更新机制 在react-dom中实现 不同平台更新内容可能不同
  25. this.updater.enqueueSetState(this, partialState, callback, 'setState');
  26. };
  27. //在Component的深层次改变但是没有调用setState时 调用此方法 强制更新一次
  28. Component.prototype.forceUpdate = function (callback) {
  29. this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
  30. };

4.PureComponent源码解析

  1. function ComponentDummy() { }
  2. // ComponentDummy的原型继承Component的原型
  3. ComponentDummy.prototype = Component.prototype;
  4.  
  5. function PureComponent(props, context, updater) {//构造函数属性(实例属性),会被实例共享,但不会被修改
  6. this.props = props;
  7. this.context = context;
  8. this.refs = emptyObject;
  9. this.updater = updater || ReactNoopUpdateQueue;
  10. }
  11. //不能直接继承Component 因为如果是直接继承Component 还会继承它的Constructor方法 目的:减少一些内存使用
  12. var pureComponentPrototype = PureComponent.prototype = new ComponentDummy();
  13. //实例沿着原型链向上查询,只要是自己继承的,都被认作自己的构造函数
  14. pureComponentPrototype.constructor = PureComponent;
  15. //这里做了优化 把 Component.prototype属性浅拷贝到pureComponentPrototype上 防止原型连拉长 导致方法的多层寻找 减少查询次数
  16. _assign(pureComponentPrototype, Component.prototype);
  17. //添加了这个isPureReactComponen参数 来判断是Component还是PureComponent组件
  18. pureComponentPrototype.isPureReactComponent = true;

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

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

1.shallowEqual函数解析

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

  1. function is(x, y) { //处理了基本类型的比较
  2. //1,针对+0===-0的情况
  3. //2. 针对NaN!==NanN的情况
  4. return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y
  5. ;
  6. }
  7. var is$1 = typeof Object.is === 'function' ? Object.is : is;
  8. var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
  9.  
  10. //返回值:false更新 true不更新
  11. function shallowEqual(objA, objB) {
  12. if (is$1(objA, objB)) {//基本数据类型 不更新
  13. return true;
  14. }
  15. //由于Object.is 可以对基本数据类型做一个精确的比较 如果不等只有一种情况 那就是object, objA/objB中,只要有一个不是object或为null则返回false
  16. if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
  17. return false;
  18. }
  19. //过滤掉基本数据类型 就是对象比较 首先比较长度 优化性能
  20. //比较oldProps和新的Props以及oldState和newState长度是否相同 如果长度不同则重新更新渲染 如果长度相同则不用重新渲染 如果不相等 不会往下执行 优化性能
  21. var keysA = Object.keys(objA);
  22. var keysB = Object.keys(objB);
  23. if (keysA.length !== keysB.length) {
  24. return false;
  25. }
  26. //如果key相等
  27. //如果objA的属性不在objB里,或者是objA的属性值和objB的属性值不等 则重新渲染 不考虑当keysA[i]为对象的多层问题 浅显比较 提高性能
  28. for (var i = 0; i < keysA.length; i++) {
  29. if (!hasOwnProperty$2.call(objB, keysA[i]) || !is$1(objA[keysA[i]], objB[keysA[i]])) {
  30. return false;
  31. }
  32. return true;
  33. }
  34. }
  1. 1.理解:is()函数 x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y 解决了NaN不等于NaN的情况和-0===+0的情, 实现了Object.is
  1. +0 === -0 //true
  2. NaN === NaN // false
  3. Object.is(+0, -0) // false
  4. Object.is(NaN, NaN) // true

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

3.浅比较的使用

对象的value是简单数据类型

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

对象的value有复杂数据类型

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

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

  1.  
  1.  

 

React的Component,PureComponent源码解析(二)的更多相关文章

  1. Component、PureComponent源码解析

    1.什么是Component,PureComponent? 都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nex ...

  2. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  3. RxJava2源码解析(二)

    title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...

  4. Sentinel源码解析二(Slot总览)

    写在前面 本文继续来分析Sentinel的源码,上篇文章对Sentinel的调用过程做了深入分析,主要涉及到了两个概念:插槽链和Node节点.那么接下来我们就根据插槽链的调用关系来依次分析每个插槽(s ...

  5. iOS即时通讯之CocoaAsyncSocket源码解析二

    原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查:本机地 ...

  6. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  7. Common.Logging源码解析二

    Common.Logging源码解析一分析了LogManager主入口的整个逻辑,其中第二步生成日志实例工厂类接口分析的很模糊,本随笔将会详细讲解整个日志实例工厂类接口的生成过程! (1).关于如何生 ...

  8. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  9. element-ui 源码解析 二

    Carousel 走马灯源码解析 1. 基本原理:页面切换 页面切换使用的是 transform 2D 转换和 transition 过渡 可以看出是采用内联样式来实现的 举个栗子 <div : ...

随机推荐

  1. hive删除表时直接卡死

    原因:因为以前安装的mysql,字符集都改为了utf-8. 解决方案:需要把字符集都改为latin1 首先进入mysql查看字符集 show variables like 'char%' 找到mysq ...

  2. 最近公共祖先 Lowest Common Ancestors

    基于深度的LCA算法:  对于两个结点u.v,它们的深度分别为depth(u).depth(v),对于其公共祖先w,深度为depth(w),u需要向上回溯depth(u)-depth(w)步,v需要d ...

  3. WebService 之 SoapHeader

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  4. SpringMVC的代码访问流程示意图

  5. 使用SVN更新项目后出现冲突说明

    使用Update后出现多个文件,并且报错!!  R.java.mine   R.java.r21965  R.java.r23204 下面以自动生成R.java.mine,R.java.r21965, ...

  6. 增删改查-删除(php)

    <!DOCTYPE html> <html><script type="text/javascript" src="jquery-1.11. ...

  7. scp知识点

    小伙伴的博客(详细): https://www.cnblogs.com/ppp204-is-a-VC/p/11673567.html

  8. oracle sqlplus链接和sid

    1.链接 ( 1.sqlplus /nolog 2.conn sys/sys@172.16.17.36/orcl as sysdba ) 2.sid   数据库名称 ----如:orcl 1.监听程序 ...

  9. IN中超过1000处理

    后台 所有用到IN的方法,都要考虑超过1000的可能 if(cameraIds != null && cameraIds.length > 0){sql.append(" ...

  10. 11g RAC添加用户表空间(数据文件)至文件系统(File System)的修正

    前提:非TEMP.UNDO和SYSTEM表空间,这仨是大爷,您得搂着点.来自博客园AskScuti .客户是添加临时表空间数据文件时,不小心 ADD 到了文件系统中,然后发现,后悔了,还在OS层面 R ...