背景
为了响应公司中台化的战略,6.7月份的时候做了一个中台组件的项目。
因为组件逻辑比较复杂,为了优化性能,绝大部分的组件我们都使用了PureComponent
,下面简要介绍一下PureComponent
的原理。
PureComponent
使用PureComponent
会帮你内置一个ShouldComponentUpdate
的生命周期,ShouldComponentUpdate
生命周期函数内部通过props
和state
的浅比较来决定是否需要渲染,如果之前的prevProp
和prevState
跟当前的props
,state
浅比较相同的话,就会返回false
,组件就不会进行渲染。(源代码会在之后的内容讲到)
问题:PureComponent 一定是有效的吗?
刚刚提到PureComponent
内部是以浅比较的方式实现的,那么大家都能想到如果props或state里有较为深层次的数据结构,那么就会导致浅比较判断错误,具体的可以去读读相关文章。这一点其实是没有办法避免的,如果你选择了使用PureComponent
,就需要理解并接受这一点。
接下来我们真正要谈到的是,还有其他两点容易被我们忽略而导致PureComponent
中的浅比较失败:
- 回调函数,随着ES6的箭头函数的出现,越来越多的前端开发就喜欢上了使用箭头函数来写回调,简洁明了,不需要再操心this的指向问题。然而,在使用了
PureComponent
的组件,如果你的props里传入了箭头函数或传统的回调函数,那么会直接导致PureComponent
失效,原因就在于父组件render时,这种写法实际上每次都会声明一个新的function
,这样浅比较的结果一定是true(不相等,因为新的function
意味着变量指向的内存地址发生了变化),所以这样的话,PureComponent
相当于失效了,而且因为多了一个浅比较的过程,反而会降低组件的性能。 - 字面量,如果你的
props
里传入了字面量,同理,每次父组件render
时,都会重新声明一个字面量,导致浅比较失败。
如何解决
注:bind()
会返回一个新的函数,导致组件重新渲染
class Parent extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this); // 【正确】
this.person = {
name: "张三"}
}
handleChange() {
}