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阻止更新 挂载阶段是不起作用的 更新阶段起作用 图如下
Component、PureComponent源码解析的更多相关文章
- React的Component,PureComponent源码解析(二)
1.什么是Component,PureComponent? 都是class方式定义的基类,两者没有什么大的区别,只是PureComponent内部使用shouldComponentUpdate(nex ...
- android源码解析(十七)-->Activity布局加载流程
版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...
- vueJs 源码解析 (三) 具体代码
vueJs 源码解析 (三) 具体代码 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那么今天我们就从这三 ...
- VueJs 源码解析 (四) initRender.Js
vueJs 源码解析 (四) initRender.Js 在之前的文章中提到了 vuejs 源码中的 架构部分,以及 谈论到了 vue 源码三要素 vm.compiler.watcher 这三要素,那 ...
- 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...
- iview源码解析(1)
概述 公司技术栈开始用vue主导开发,但因为公司前端会vue的不多所以在项目中用到vue的技术不是很深,之前出去面试被接连打击,而且本来打算开始为公司vue的项目构建自己的组件库所以去下载了iview ...
- @Controller和@RestController源码解析
2018年不知不觉已经走到了尾声,你还在为分不清@Controller和@Restcontroller而烦恼吗?这篇博文从源码层面分析这两个注解,值得一读. 首先贴一张源码的图,对比一下,左边是@Co ...
- Spring Security 访问控制 源码解析
上篇 Spring Security 登录校验 源码解析 分析了使用Spring Security时用户登录时验证并返回token过程,本篇分析下用户带token访问时,如何验证用户登录状态及权限问 ...
- redux的源码解析
一. redux出现的动机 1. Javascript 需要管理比任何时候都要多的state2. state 在什么时候,由于什么原因,如何变化已然不受控制.3. 来自前端开发领域的新需求4. 我们总 ...
随机推荐
- 1131 - Just Two Functions
1131 - Just Two Functions PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...
- CS5212Capstone|DP转VGA方案设计芯片|CS5212设计资料
CS5212是台湾CAPSTONE最新开发出一款用于DP转VGA方案设计芯片,其周围器件较少,设计简单,整体BOM成本低,市场性价比较高. CS5212内置MCU是工业标准8051核心单片机处理器.C ...
- 基于Spring MVC + Spring + MyBatis的【学生管理管理系统】
资源下载:https://download.csdn.net/download/weixin_44893902/45602690 练习点设计:模糊查询.删除.新增 一.语言和环境 实现语言:JAVA语 ...
- Java初学者作业——编写JAVA程序,要求输入技术部门5位员工的理论成绩和实操成绩,计算并输出各位员工的最终评测成绩。
返回本章节 返回作业目录 需求说明: 某软件公司要求对技术部门的所有员工进行技能评测,技术评测分为两个部分:理论部分以及实操部分,最终评测成绩=理论成绩×0.4+实操成绩×0.6,要求输入技术部门5位 ...
- linux 之 非root用户安装mysql5.7.27
下载 下载 mysql-5.7.27-linux-glibc2.12-x86_64.tar.gz 详见linux(CentOS7) 之 MySQL 5.7.30 下载及安装. 配置规划 用户: zhj ...
- java 使用 ArrayList 排序【包括数字和字符串】
1.数字排序 /** * 数字排序 */ @Test public void t2() { List<Integer> list = new ArrayList<>(); li ...
- 硬核 - Java 随机数相关 API 的演进与思考(上)
本系列将 Java 17 之前的随机数 API 以及 Java 17 之后的统一 API 都做了比较详细的说明,并且将随机数的特性以及实现思路也做了一些简单的分析,帮助大家明白为何会有这么多的随机数算 ...
- 安装TestNG
1.启动Eclipse,选择"Help"-->'Install New Software' 2.在谈出的弹框中选择"Add" 3.在弹出的"Ad ...
- Numpy实现简单BP神经网络识别手写数字
本文将用Numpy实现简单BP神经网络完成对手写数字图片的识别,数据集为42000张带标签的28x28像素手写数字图像.在计算机完成对手写数字图片的识别过程中,代表图片的28x28=764个像素的特征 ...
- synchronized锁升级详细过程
java对象头由3部分组成: 1.Mark Word 2.指向类对象(对象的class对象)的指针 3.数组长度(数组类型才有) 重点是 Mark Word结构,下面以32位HotSpot为例: 一. ...