react性能优化之组件render优化

举个例子说明,父组件触发 render,无论子组件使用到父组件的 state 作为 props 值是否改变,甚至无论子组件是否使用到父组件的 state,都会触发子组件 render

class ChildOne extends React.Component {
    constructor(props) {
        super(props)
    }

    render() {
        const {value} = this.props;
        console.log('触发子组件 ChildOne 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildOne</p>
                <div> 父组件传入 props 数据{value}</div>
            </div>
        );
    }
}

class ChildTwo extends React.Component {
    constructor(props) {
        super(props)
    }

    render() {
        console.log('触发子组件 ChildTwo 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildTwo</p>
            </div>
        );
    }
}

class App extends React.Component {
    state = {
        value: 1,
    };

    handleClick = () => {
        this.setState({
            value: 1
        });
    };

    render() {
        console.log('触发父组件的 render')
        return (
            <React.Fragment>
                <div className="box">
                    <div>{this.state.value}</div>
                    <button onClick={this.handleClick}>+</button>
                </div>
                <ChildOne value={this.state.value}/>
                <ChildTwo/>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"))

对于 react 的 class 组件,我们可以使用 PureComponent 处理基本数据类型

class ChildOne extends React.PureComponent {
    constructor(props) {
        super(props)
    }

    render() {
        const {value} = this.props;
        console.log('触发子组件 ChildOne 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildOne</p>
                <div> 父组件传入 props 数据{value}</div>
            </div>
        );
    }
}

class ChildTwo extends React.PureComponent {
    constructor(props) {
        super(props)
    }

    render() {
        console.log('触发子组件 ChildTwo 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildTwo</p>
            </div>
        );
    }
}

class App extends React.Component {
    state = {
        value: 1,
    };

    handleClick = () => {
        this.setState({
            value: 1
        });
    };

    render() {
        console.log('触发父组件的 render')
        return (
            <React.Fragment>
                <div className="box">
                    <div>{this.state.value}</div>
                    <button onClick={this.handleClick}>+</button>
                </div>
                <ChildOne value={this.state.value}/>
                <ChildTwo/>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"))

PureComponent,浅比较只能比较基本数据类型的异同,如果传入的 props 是复杂数据类型 子组件render仍然会触发 举个例子

class ChildOne extends React.PureComponent {
    constructor(props) {
        super(props)
    }

    render() {
        const {value} = this.props;
        console.log('触发子组件 ChildOne 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildOne</p>
                <div> 父组件传入 props 数据{value.number}</div>
            </div>
        );
    }
}

class App extends React.Component {
    state = {
        value: {
            number: 1,
        }
    };

    handleClick = () => {
        this.setState({
            value: {
                number: 1
            }
        });
    };

    render() {
        console.log('触发父组件的 render')
        return (
            <React.Fragment>
                <div className="box">
                    <div>{this.state.value.number}</div>
                    <button onClick={this.handleClick}>+</button>
                </div>
                <ChildOne value={this.state.value}/>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"))

shouldComponentUpdate 处理复杂数据类型

class ChildOne extends React.Component {
    constructor(props) {
        super(props)
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log('nextProps', nextProps)
        console.log('this.props', this.props)
        return nextProps.value.number !== this.props.value.number
    }

    render() {
        console.log('触发子组件 ChildTwo 的 render')
        return (
            <div className="box">
                <p> 子组件 ChildTwo</p>
            </div>
        );
    }
}

class App extends React.Component {
    state = {
        value: {
            number: 1,
        }
    };

    handleClick = () => {
        this.setState({
            value: {
                number: 1
            }
        });
    };

    render() {
        console.log('触发父组件的 render')
        return (
            <React.Fragment>
                <div className="box">
                    <div>{this.state.value.number}</div>
                    <button onClick={this.handleClick}>+</button>
                </div>
                <ChildOne value={this.state.value}/>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"))

前面是 class 组件的优化方式,那么对于函数式组件,我们又该如何处理呢?
react 很贴心的提供了 React.memo() 高阶组件,他的功能与 PureComponent 类似: 以下例子 ChildOne 触发render ChildTwo 不触发render

const ChildOne = props => {
  console.log('触发子组件 ChildOne 的 render')
  return (
      <div className="box">
          <p> 子组件 ChildOne</p>
          <div> 父组件传入 props 数据{props.value.number}</div>
      </div>
  )
};

const ChildTwo = React.memo(() => {
  console.log('触发子组件 ChildTwo 的 render')
  return (
      <div className="box">
          <p> 子组件 ChildTwo</p>
      </div>
  )
})


class Home extends React.Component {
  state = {
    value: {
      number: 1,
    },
  };

  handleClick = () => {
    this.setState({
      value: {
        number: 1,
      },
    });
  };

  componentDidMount() {}
  render() {
    // return <div className="test">Home</div>;
    console.log("触发父组件的 render");
    return (
      <React.Fragment>
      <div className="box">
          <div>{this.state.value.number}</div>
          <button onClick={this.handleClick}>+</button>
      </div>
      <ChildOne value={this.state.value}/>
      <ChildTwo/>
  </React.Fragment>
    );
  }
}

React.memo() 高阶组件处理复杂类型

const ChildOne = React.memo(props => {
    console.log('触发子组件 ChildTwo 的 render')
    return (
        <div className="box">
            <p> 子组件 ChildOne</p>
            <div> 父组件传入 props 数据{props.value.number}</div>
        </div>
    )
}, areEqual)

function areEqual(prevProps, nextProps) {
    console.log('prevProps', prevProps)
    console.log('nextProps', nextProps)
    return prevProps.value.number === nextProps.value.number
}

class App extends React.Component {
    state = {
        value: {
            number: 1,
        }
    };

    handleClick = () => {
        this.setState({
            value: {
                number: 1
            }
        });
    };

    render() {
        console.log('触发 render')
        return (
            <React.Fragment>
                <div className="box">
                    <div>{this.state.value.number}</div>
                    <button onClick={this.handleClick}>+</button>
                </div>
                <ChildOne value={this.state.value}/>
            </React.Fragment>
        );
    }
}

ReactDOM.render(<App/>, document.getElementById("root"))

总结xmind图

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值