如何实现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 国际许可协议 进行许可。转载请注明出处!