React中Component存在的性能问题

394 阅读2分钟

Componment存在的问题?

父组件重新render(),当前组件的子组件也会重新执行render(),即使state没有任何变化

当前组件setState(),会重新执行render(),即使state没有任何变化

解决Component存在的问题?

原因: 组件的shouldComponentUpdate ()默认返回true,即使数据没有变化,render()也会重新执行

方法1: 重写 shouldComponentUpdate () 方法,判断数据是否发生变化,发生变化返回true,反之返回false

方法2: 使用PureComponent代替Component

**说明:**一般使用PureComponent来优化组件性能

案例

1、点击 ‘测试-App’ 按钮,App组件和B组件都会重新渲染
2、即使 App组件不向B组件传递数据,B组件也会重新渲染
3、即使App组件中没有数据变化,但是只要使用了 setState({}) B组件也会重新渲染
4、当state和props中的状态都没有更新的时候,不让B组件重新渲染
   - 在B组件中使用 shouldComponentUpdate ,代码如下	
5、当state和props中的状态都没有更新的时候,不让B组件重新渲染
   - 使用PureComponent 代替 Component
   - class B extends React.Component 改为 class B extends React.PureComponent
 	class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          m1: 1
        }
      }
      test1 = ()=> {
        this.setState(state => ({
           m1: state.m1 + 1
         }))
         this.setState({}); // 这样写B组件也会重新渲染 
      }
      render() {
        console.log('render-App');
        return (
          <div>
            <h1>{this.state.m1}</h1>
            <button onClick={this.test1}>测试-App</button>    
            <B m1={this.state.m1} />        
          </div>
        )
      }
    }
    class B extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          m2: 1
        }
      }
      test2 = ()=> {
        this.setState(state => ({
          m2: state.m2 + 1
        }))
      }
       /**
        默认返回true,即使数据没有变化,render()都会重新执行
        重写 componentShouldUpdate() 方法,判断数据是否发生变化,发生变化返回true,反之返回false
       */
      shouldComponentUpdate(nextProps, nextState) {
        // 比较新旧props和state中的数据,如果没有一个变化返回false,返回返回true
        if(this.props.m1 === nextProps.m1 && this.state.m2 === nextState.m2) {
          return false;
        } else {
          return true;
        }
      }
      render() {
        console.log('render-B');
        return (
          <div>
            <h1>m2={this.state.m2},m1={this.props.m1}</h1>
            <button onClick={this.test2}>测试--B</button>            
          </div>
        )
      }
    }

常见Bug

子组件使用 PureComponent

父组件在更新一个引用数据类型的数据时使用下面的方式:

state = { 
   m1:{ count:0} 
}

click1 = ()=> {
    
    const m1 = this.state.m1;
    m1.count = 2;
    // 这种写法是错误的,因为m1对象本身并没有发生变化,只是内部的数据发生了变化,
    // 所以如果子组件使用的是PureComponent那么子组件是不会更新的
    this.setState({m1});
    
    // 下面这种写法是正确的:子组件会被更新
    this.setState({m1:[...m1]})
}