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阻止更新 挂载阶段是不起作用的  更新阶段起作用 图如下

												

Component、PureComponent源码解析的更多相关文章

  1. React的Component,PureComponent源码解析(二)

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

  2. android源码解析(十七)-->Activity布局加载流程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...

  3. vueJs 源码解析 (三) 具体代码

    vueJs 源码解析 (三) 具体代码 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那么今天我们就从这三 ...

  4. VueJs 源码解析 (四) initRender.Js

    vueJs 源码解析 (四) initRender.Js 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那 ...

  5. 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器

    写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...

  6. iview源码解析(1)

    概述 公司技术栈开始用vue主导开发,但因为公司前端会vue的不多所以在项目中用到vue的技术不是很深,之前出去面试被接连打击,而且本来打算开始为公司vue的项目构建自己的组件库所以去下载了iview ...

  7. @Controller和@RestController源码解析

    2018年不知不觉已经走到了尾声,你还在为分不清@Controller和@Restcontroller而烦恼吗?这篇博文从源码层面分析这两个注解,值得一读. 首先贴一张源码的图,对比一下,左边是@Co ...

  8. Spring Security 访问控制 源码解析

    上篇 Spring Security 登录校验 源码解析  分析了使用Spring Security时用户登录时验证并返回token过程,本篇分析下用户带token访问时,如何验证用户登录状态及权限问 ...

  9. redux的源码解析

    一. redux出现的动机 1. Javascript 需要管理比任何时候都要多的state2. state 在什么时候,由于什么原因,如何变化已然不受控制.3. 来自前端开发领域的新需求4. 我们总 ...

随机推荐

  1. P1599 货币

    背景 又是一道水题 描述 在某个神秘的星球上有一种货币,它有一种奇怪的兑换规则 你有且仅有一枚面值为n的金币,你可以去银行进行兑换,也可以不兑换 如果去银行兑换,兑换的规则是这样的:用面值为a的金币去 ...

  2. python学习第二天:命令行模式和python交互模式

    命令行模式 安装完python开发环境和工具之后,在Windows开始菜单选择"命令提示符",就会进入到命令行模式: 或者都可以,然后 点击enter键,弹出下图中的窗口,即命令行 ...

  3. 《HelloGitHub》第 69 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

  4. uniapp 兼容H5复制文本功能,亲测可用

    封装copyText函数,具体如下: copyText(val){ let result // #ifndef H5 uni.setClipboardData({ data: val, success ...

  5. 对vector和map容器的删除元素操作

    /** * 删除头部元素 * 切割map到指定的个数 * @param map * @param i * @return */ map<int, Rect> PublicCardFrame ...

  6. linux 设置开机自动启动应用

    作为一个开发,项目现在一般都是部署在虚拟机上的linux,数据库也是按照在l虚拟机上的linux,一旦关机了,在开机程序都没打开,又要一个个去开,很麻烦,所以现在我现在使用supervisor去做一个 ...

  7. Sentry 企业级数据安全解决方案 - Relay 监控 & 指标收集

    内容整理自官方文档 系列 Sentry 企业级数据安全解决方案 - Relay 入门 Sentry 企业级数据安全解决方案 - Relay 运行模式 Sentry 企业级数据安全解决方案 - Rela ...

  8. 由浅入深学习Apache httpd原理与配置

    一.apache简介: Apache HTTPD又可以简称为httpd或者Apache,它是Internet使用最广泛的web服务器之一,使用Apache提供的web服务器是由守护进程httpd,通过 ...

  9. Echart可视化学习(五)

    文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 常见的数据可视化库: D3.js ...

  10. vue3.0+vite+ts项目搭建(报错处理)

    报错一 warning package.json: No license field$ vue-tsc --noEmit && vite build 解决方案,添加这两行,只添加一个是 ...