React.PureComponent(React组件优化)
React.PureComponent:
就是基于浅比较的方式,给每一个组件设置shouldComponentUpdate(如果自己设置了,以自己的为主),在里面把状态和属性都做对比,如果两者基于浅比较都没有发生任何的更改,则不再重新渲染组件
setStart有个小毛病
虽然说是改变状态并且通知组件重新渲染,但是我们不改状态值,也通知组件重新渲染了shouldComponentUpdate => componentWillUpdate ...
forceUpdate:=>componentWillUpdate (跳过SHOULD步骤)
- 好了!我们先通过一个小案例感受一下PureComponent部分源码,
import React from 'react';
import PropTypes from 'prop-types';
/*
* React.PureComponent
*/
//=>把两个对象进行浅比较
// 只比较对象的第一级
// 如果属性值是基本类型的,我们只需要比较值是否一样即可
function shallowEqual(obj1, obj2) {
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false;
}
for (let key in obj1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
class CountShow extends React.Component {
render() {
return <div>
{this.props.num}
</div>;
}
}
export default class Count extends React.Component {
state = {
num: 0,
x: 100,
arr: [10, 20]
};
render() {
console.log('OK');
return <>
<CountShow num={this.state.num} />
<button onClick={ev => {
this.state.arr.push(30);
this.setState({
arr: [...this.state.arr]
});
}}>累加</button>
</>;
}
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqual(this.state, nextState) || !shallowEqual(this.props, nextProps);
}
}
浅比较就是只比较第一级,对于基本数据类型,只比较值;对于引用数据类型值,直接比较地址是否相同,不管里面内容变不变,只要地址一样,我们就认为没变。所以在这种情况下,我们以后用的时候,对于引用类型值修改状态或修改属性时候,对于它赋值的时候,我们尽可能把之前值拿过来克隆一份,赋给它新的地址就好~这是我们的注意点!我们想做性能优化的时候就可以在Component里做一个浅比较。
=>React.PureComponent是基于浅比较,所以只要属性值是引用类型,但是修改后的值变了,但是地址不变,也不会重新渲染
以下这段是注释---
/*
this.state.arr.push(30)
setState({
arr:this.state.arr 不会通知重新渲染
arr:[...this.state.arr] 这样是会通知的(堆内存地址变了)
})
=>PureComponent对forceUpdate无效(forceUpdate根本不走shouldComponentUpdate)
=>父组件是PureComponent那么子组件也具备了同样的功效(因为父组件不渲染,子组件也不会渲染)
*/
PureComponent使用方法
- 还是用同样的小案例,不过比自己写方法方便的多,直接把React.Component替换成React.PureComponent即可~
import React from 'react';
import PropTypes from 'prop-types';
class CountShow extends React.Component {
render() {
return <div>
{this.props.num}
</div>;
}
}
export default class Count extends React.PureComponent {
state = {
num: 0,
x: 100,
arr: [10, 20]
};
render() {
console.log('OK');
return <>
<CountShow num={this.state.num} />
<button onClick={ev => {
this.state.arr.push(30);
this.setState({
arr: [...this.state.arr]
});
}}>累加</button>
</>;
}
}
注意
- 注:PureComponent不能乱用,只有那些状态和属性不经常的更新的组件我们用来做优化,对于经常更新的,这样处理后反而浪费性能,因为每一次浅比较也是要消耗时间的