React 之性能优化

2018-08-23  本文已影响32人  PoWerfulHeart

一.包含父子组件的Tab切换

当我们将tab切换分离到子组件时很多人喜欢这样写
父组件:

class App extends Component{
  constructor(props){
    super(props);
    this.state = {
    };
    this.type = 0;
  }

 tabSwitch(){
     this.setState({
           //change state
     })
 }

  render(){
    return (
          <Tab renderFun={this.tabSwitch} type={this.type}  />
    )
  }
} 

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

子组件:

export default class Tab extends Component{
    constructor(props){
      super(props);
      this.state = {
        tab:['tab1','tab2'],
        current:this.props.type
      };
    }

    tabSwitch(index){
      this.setState({
        current:index
      },() => {
        this.props.renderFun(this.state.current);
      })
    }

    render(){
    var _this = this;
    return (
       <div className='tab'>
           { this.state.tab.map(function(ele,index){
                    return <div key={index} className={'tab_' + index + ' ' + (_this.state.current == index ? 'tab_active':'')} onClick={_this.tabSwitch.bind(_this,index)}>{ele}</div>
             })
           }
       </div>
    )
  }
}

这样的写法实现功能是没问题。当我们切换tab时,将点击的tab栏目传递给父组件,父组件改变state去重新渲染tab列表。但是这里虽然功能实现,但是这样会有重复渲染的问题出现。

组件更新过程:shouldComponentUpdate=》componentWillUpdate-》render-》componentDidUpdate

我们在子组件点击的时候,setState改变了current,子组件重新渲染,然后回调点击的tab给父组件,父组件执行setState会开始更新过程,这时候父组件的shouldComponentUpdate未设置,默认是true,父组件完成了更新过程,由于父组件的渲染,所以子组件也开始更新过程,此时shouldComponentUpdate也是true,子组件也会完成更新过程。子组件相当于重复渲染了一次

正确的写法:

React建议将关系到渲染的数据保存在state中。这里能勾关系到渲染的就是这个type了。因为type的改变会导致我们的列表改变
父组件:

class App extends Component{
  constructor(props){
    super(props);
    this.state = {
          type:0
    };
  }

 tabSwitch(index){
     this.setState({
          type:index
     })
 }

  render(){
    return (
          <Tab renderFun={this.tabSwitch} type={this.state.type}  />
    )
  }
} 

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

子组件:

export default class Tab extends Component{
    constructor(props){
      super(props);
      this.state = {
        tab:['tab1','tab2'],
      };
          this.current = this.props.type;
    }

       shouldComponentUpdate(newProps, newState) {
        return newProps.type !== this.props.type;    //此时返回false,子组件不会被重复渲染
    }

    tabSwitch(index){
     this.current = index;
     this.props.renderFun(index);
    }

    render(){
    var _this = this;
    return (
       <div className='tab'>
           { this.state.tab.map(function(ele,index){
                    return <div key={index} className={'tab_' + index + ' ' + (_this.current == index ? 'tab_active':'')} onClick={_this.tabSwitch.bind(_this,index)}>{ele}</div>
             })
           }
       </div>
    )
  }
}
上一篇 下一篇

猜你喜欢

热点阅读