1.前言
1. React.PureComponent与React.Component几乎完全相同,
但React.PureComponent通过props和state的浅对比来实现
shouldComponentUpdate()
2. 在PureComponent中,如果包含比较复杂的数据结构,可能会因深层的数据不一致而产生错误的否定判断,导致界面得不到更新。
3. 如果定义了shouldComponentUpdate(),无论组件是否是PureComponent,
它都会执行shouldComponentUpdate(),并根据结果来判断是否update界面。
如果组件未实现shouldComponentUpdate(),则会判断该组件是否是PureComponent,
如果是PureComponent,会对新、旧props、state进行shallowEqual比较
(shallow: 浅的 <----> deep: 深的)
4. 浅对比
通过遍历对象上的键值是否相等,当键值不等返回false
当所有键的值相等时返回true
二、区别
PureComponent自带通过props和state的浅对比来实现shouldComponentUpdate()
而Component没有
1. PureComponent的缺点
可能会因为深层的数据不一致而产生错误的否定判断,从而shouldComponentUpdate
结果返回false,界面不会更新
2. PureComponent优势
不需要开发者自己实现shouldComponentUpdate,就可以进行简单的判断来提升性能
- JavaScript中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。
- 简单来说,就是指针引用,两个变量指向的地址是相同的。这也是浅拷贝机制。
function shallowEqual(objA, objB) -> boolean {
// 1.首先判断是否相等,相等返回true
// 这里就会存在漏洞了,如果浅拷贝一个数组对象,对象地址指向这里
// 就算修改了数组中的内容,但是地址是不会变的
// 那么用浅拷贝的对象和原来的对象去对比,会发现:
// 1. 虽然数组的内容发送了变化
// 2. 但是两个对象的地址是同一个,就会认为相等了,导致误判断
if (objA === objB) {
return true;
}
// 2. 如果不相等,obj为空或不为object类型,返回false
// 为空了,或者不为object了,肯定也是不相等
if (typeof objA !== 'object' || objA === null ) || (typeof objB !== 'object' || objB === null) {
return false;
}
// 3. 获取obj的keys集合,如果两者的长度不相等,就返回false
// 长度都不相等,两者肯定不相等
let keysA = Object.keys(objA)
let keysB = Object.keys(objB)
if (keysA.length !== keysB.length) {
return false
}
// 4. 循环遍历
// 如果长度相等,就挨个key进行比较
// 如果另一个obj不含有key, 返回false
// 如果两个obj的key的值不相等,也返回false
for (const key of keysA) {
if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
return false
}
}
// 5. 能来到这里,就返回true
return true
}
- 解决方法
要用深拷贝,三个点的语法,对原来的对象深拷贝,这样地址就不一样了
this.setState(prevState => ({
numbers: [...prevState.numbers, 1],
}));