如何实现react的组件优化
本篇文章将通过一个小案例进行分析。假设有一个Parent组件,子组件是Child组件,通过点击按钮使得Parent组件中的state数据改变,通过props将数据传递给Child,分析每次修改数据父子组件是否重新渲染。
1 React.Component
定义 class 组件,需要继承 React.Component。
Parent.jsx中代码:
import React, { Fragment, Component } from 'react';
class Parent extends Component {
state = {
name: 'liaoxin'
}
changeName = () => {
this.setState({
name: 'xinxin'
})
//this.setState({})
}
render() {
console.log('Parent render')
return (
<Fragment>
<h1>Parent组件,当前姓名为:{this.state.name}</h1>
<button onClick={this.changeName}>点击切换姓名</button>
<hr/>
<Child name={this.state.name}></Child>
{/* <Child ></Child> */}
</Fragment>
);
}
}
class Child extends Component {
render() {
console.log('Child render')
return (
<Fragment>
<h1>Child组件,接收到的Parent姓名为:{this.props.name}</h1>
</Fragment>
);
}
}
export default Parent;
执行结果如下图
可以发现:
1.只要执行setState(),即使不改变状态数据, 组件也会重新render(),这样就会造成效率低。
2.只要当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据,这样就会造成效率低。
1.2 原因
Component中的shouldComponentUpdate()总是返回true。
我们所希望的是只有当组件的state或props数据发生改变时才重新render()。
1.3 解决办法
1.重写shouldComponentUpdate()方法
比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
class Parent extends Component {
state = {
name: 'liaoxin'
}
changeName = () => {
this.setState({
name: 'xinxin'
})
//this.setState({})
}
shouldComponentUpdate(nextProps,nextState){
console.log('Parent组件的props,state')
console.log(nextProps,nextState)
if(this.state.name === nextState.name){
return false
}else {
return true
}
}
render() {
console.log('Parent render')
return (
<Fragment>
<h1>Parent组件,当前姓名为:{this.state.name}</h1>
<button onClick={this.changeName}>点击切换姓名</button>
<hr/>
<Child name={this.state.name}></Child>
{/* <Child ></Child> */}
</Fragment>
);
}
}
class Child extends Component {
shouldComponentUpdate(nextProps,nextState){
console.log('Child组件的props,state')
console.log(nextProps,nextState)
if(this.props.name === nextProps.name){
return false
}else {
return true
}
}
render() {
console.log('Child render')
return (
<Fragment>
<h1>Child组件,接收到的Parent姓名为:{this.props.name}</h1>
</Fragment>
);
}
}
export default Parent;
执行结果如下图,继续点击父子组件将不再render
2.使用PureComponent
PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true。
2 React.PureComponent
如果赋予 React 组件相同的 props 和 state,render() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent 可提高性能。
在Parent.jsx中
import React, { Fragment, PureComponent } from 'react';
class Parent extends PureComponent {
state = {
name: 'liaoxin'
}
changeName = () => {
this.setState({
name: 'xinxin'
})
//this.setState({})
}
render() {
console.log('Parent render')
return (
<Fragment>
<h1>Parent组件,当前姓名为:{this.state.name}</h1>
<button onClick={this.changeName}>点击切换姓名</button>
<hr/>
<Child name={this.state.name}></Child>
{/* <Child ></Child> */}
</Fragment>
);
}
}
class Child extends PureComponent {
render() {
console.log('Child render')
return (
<Fragment>
<h1>Child组件,接收到的Parent姓名为:{this.props.name}</h1>
</Fragment>
);
}
}
export default Parent;
将changeName函数修改为如下代码,可以发现界面并未更新。不要直接修改state数据, 而是要产生新数据。
changeName = () => {
// this.setState({
// name: 'xinxin'
// })
const obj = this.state
obj.name = 'xinxin'
this.setState(obj)
}
注意
React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的 props 和 state 较为简单时,才使用 React.PureComponent,或者在深层数据结构发生变化时调用 forceUpdate() 来确保组件被正确地更新。
- 本文作者: étoile
- 版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!