React.PureComponent(React组件优化之浅比较)

5,099 阅读2分钟

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不能乱用,只有那些状态和属性不经常的更新的组件我们用来做优化,对于经常更新的,这样处理后反而浪费性能,因为每一次浅比较也是要消耗时间的