PureComponent踩坑

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了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值