PureComponent
react 中的PureComponent区别于 Component ,是为了进一步优化shouldComponentUpdate的。
在组件中的优先级顺序是
你写的shouldComponentUpdate>
PureComponent中的shouldComponentUpdate>
Component中默认的shouldComponentUpdate
大家都知道在react中的shouldComponent的作用,是通过diff算法来判断页面是否需要进行更新的。
那么在PureComponent中,它的diff算法是一种浅对比,它只对对象进行一层的对比,如果有更深层的数据发生改变,它会被判定为没有改变,从而在你setState的时候不对数据进行改变。
- PureComponent 的数据比较源码:
//is函数用来判断 ’ 数据类型&&数据 ‘是否一致
function is(x: mixed, y: mixed): boolean {
if (x === y) {
// 1 / x === 1 / y 用来判断0与-0,得到Infinity ===-Infinity false
return x !== 0 || y !== 0 || 1 / x === 1 / y;
} else {
//严谨,判断Nan类型数据
return x !== x && y !== y;
}
}
function shallowEqual(objA: mixed, objB: mixed): boolean {
//首先判断两者的数据类型
if (is(objA, objB)) {
return true;
}
//判断不是object,返回false
if (typeof objA !== 'object' || objA === null ||
typeof objB !== 'object' || objB === null) {
return false;
}
//获取object中的所有键
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
//对比两者长度
if (keysA.length !== keysB.length) {
return false;
}
// 如果key数量相同,使用一层for循环去比较
for (let i = 0; i < keysA.length; i++) {
if (
!hasOwnProperty.call(objB, keysA[i]) ||
!is(objA[keysA[i]], objB[keysA[i]])
) {
return false;
}
}
return true;
}
知识点
之所以PureComponent会对比出错,原因是js是进行引用赋值的
let obj1 = {name:'张三',age:24}
let obj2 = obj1
obj1 == obj2//true
obj1 === obj2//true
两个东西obj1 和obj2 其实指向的是同一块引用地址,也就是说他们俩用的是同一个数据,不管谁变了,另一个也会变。
let obj1 = {name:'张三',age:24}
let obj2 = obj1
obj2.age = 25
console.log(obj1)//{name:'张三',age:25}
console.log(obj2)//{name:'张三',age:25}
- 情景
constructor(props) {
super(props);
this.state = {
obj:{name:'张三',age:25}
}
componentDidMount(){
let obj2 = this.state.obj
obj2.age = 40
this.state({
obj:obj2
})
}
render(){
return <div>年龄:{this.state.obj.age}</div>
}
上面的代码在运行之后,本来应该显示的age是40,但是实际上显示的是25,原因就是PureComponent判定obj 与obj2 两个是同一个数值而不进行数据的更新。
解决浅对比的方法
- 使用副本来返回新的变量
this.setState(prevState => ({
words: [...prevsState],
}));
- 使用临时副本
this.setState({
list:[].concat(newList)
})
- deepclone直接创建一个新数据
这个是昨天fix的最后一个问题所在,小记。
组件中层级比较深的最好就不要用PureComponent了