我们先来看一个例子:
App有一个counter计数器,同时还有子组件Home,当点击按钮+1后,App的render函数会被调用,但同时我们发现Home组件的render函数也被调用了10次。
那么,我们思考一下,在以后的开发中,我们只要是修改了App中的数据,所有的组件都需要重新render,进行diff算法,那性能必然是很低的。
- 实际上,很多组件没有必要重新调用render函数
- 他们调用render函数应该有一个前提,就是依赖的数据(state、props) 发生改变时才调用。
那么如何来进行优化呢?
一、使用shouldComponentUpdate方法进行优化
-
React的生命周期方法shouldComponentUpdate,这个方法接受参数,并且需要有返回值:
-
该方法有两个参数:
- 参数一:nextProps修改之后,最新的props属性
- 参数二:nextState修改之后,最新的state属性
-
该方法返回值时是一个boolean类型:
- 返回值为true,那么就需要调用render方法
- 返回值为false,那么就不需要调用render方法
- 默认返回的是true
下面的例子中,在子组件中增加一个shouldComponentUpdate方法来优化调用render
Home组件render函数只有在初次渲染的时候调用了一次,后面counter发生改变的时候,render函数并被没有调用。
class Home extends Component {
shouldComponentUpdate(nextProps,nextState){
if(this.props.name !== nextProps.name) {
return true;
}
return false;
}
render() {
const {name} = this.props;
console.log("Home组件的render函数,组件被渲染了");
return <div><h2>Home Page</h2><h3>我的名字:{name}</h3></div>;
}
}
class App extends Component {
constructor() {
super();
this.state = {
name: 'kobe',
counter: 100
};
}
render() {
const { name,counter } = this.state;
return (
<div>
<h2>App page: { counter } </h2>
<button onClick={e=> this.setState({counter: counter+1}) }>+1</button>
<hr />
<Home name={name}></Home>
</div>
);
}
}
二、PureComponent
如果所有的类,我们都需要手动来实现shouldComponentUpdate,那么会给我们开发者增加非常多的工作量。**
可以考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。
三、高阶组件memo
const Home = memo((props) => {
const { name } = props;
console.log("Home组件的render函数,组件被渲染了");
return (
<div>
<h2>Home Page</h2>
<h3>我的名字:{name}</h3>
</div>
);
});
函数式组件在props没有改变时,也是不希望其重新渲染其DOM树结构的。