当一个组件的props或state变更,React 会将最新返回的元素与之前渲染的元素进行对比,以此决定是否有必要更新真实的 DOM,当它们不相同时 React 会更新该 DOM。
如果渲染的组件非常多时可以通过覆盖生命周期方法 shouldComponentUpdate 来进行优化 shouldComponentUpdate 方法会在重新渲染前被触发。其默认实现是返回 true,如果组件不需要更新,可以在shouldComponentUpdate中返回 false 来跳过整个渲染过程。其包括该组件的 render 调用以及之后的操作。
PureComponent通过prop和state的浅比较来实现shouldComponentUpdate。
import React from 'react';
import {Button,message} from 'antd';
import PureComponent from './PureComponent';
export default class App extends PureComponent{
state = {
title:'计数器',
number:0
}
add = ()=>{
this.setState({number:this.state.number+parseInt(this.amount.value)});
}
render(){
console.log('App render');
return (
<div>
<Title2 title={this.state.title}/>
<Counter number={this.state.number}/>
<input ref={inst=>this.amount = inst}/>
<button onClick={this.add}>+</button>
</div>
)
}
}
class Counter extends PureComponent{
render(){
console.log('Counter render');
return (
<p>{this.props.number}</p>
)
}
}
//类组件可以用继承
class Title extends PureComponent{
render(){
console.log('Title render');
return (
<p>{this.props.title}</p>
)
}
}
//函数组件可以和memo
const Title2 = React.memo(props=>{
console.log('Title2 render');
return <p>{props.title}</p>;
});
//memo的实现
function memo(func){
class Proxy extends PureComponent{
render(){
return func(this.props);
}
}
return Proxy;
}
//memo的另一种实现 接收一个函数组件
function memo2(Func){
class Proxy extends PureComponent{
render(){
return <Func {...this.props}/>
}
}
return Proxy;
}
上面的代码在实现 memo 中使用了 PureComponent,那么重点我们实现一下这个组件。
import React from 'react';
function shallowEqual(obj1,obj2){
if(obj1 === obj2){
return true;
}
if(typeof obj1 != 'object' || obj1 === null ||typeof obj2 != 'object' || obj2 === null ){
return false;
}
let keys1 = Object.keys(obj1);
let keys2 = Object.keys(obj2);
if(keys1.length != keys2.length){
return false;
}
for(let key of keys1){
if(!obj2.hasOwnProperty(key) || obj1[key] !== obj2[key]){
return false;
}
}
return true;
}
export default class PureComponent extends React.Component{
isPureReactComponent = true
shouldComponentUpdate(nextProps,nextState){
return !shallowEqual(this.props,nextProps)||!shallowEqual(this.state,nextState)
}
}