React組件中的事件處理函數

在react中實現事件處理,有多種寫法,那那種寫法相對更優,更利於React的渲染性能呢?前端

React組件中添加事件處理的幾種方式

constructor函數中bind

class ReactEvent extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('Click');
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

使用箭頭函數(實驗語法,還沒有標準化)

render中使用箭頭函數

class ReactEvent extends Component {

  handleClick() {
    console.log('Click');
  }

  render() {
    return <button onClick={() => this.handleClick()}>Click Me</button>;
  }
}

使用class fields語法(https://babeljs.io/docs/en/ba...

class ReactEvent extends Component {

  //此函數會被綁定到ReactEvent類的實例
  handleClick = () => {
    console.log('Click');
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}

在render中使用bind

class ReactEvent extends Component {

  handleClick() {
    console.log('Click');
  }

  render() {
    return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
  }
}

幾種方式比較

影響 constructor函數中bind 使用class fields語法 render中使用箭頭函數 在render中使用bind
render時生成新函數
性能 無影響 無影響 有影響 有影響
可直接攜帶參數
簡潔性 很差

  上表中咱們看到,在render中直接bind或者箭頭函數都會影響性能,緣由在於,在render 中的bind和箭頭函數在每次render時都會建立新的函數,致使子組件的props發生改變,這在PureComponent中會影響性能,除非本身在shouldComponentUpdate中進行優化。react

bind和箭頭函數相關請參考mdn:
https://developer.mozilla.org...
https://developer.mozilla.org...
//僅做爲示例代碼,不遵循經常使用代碼規範
//子組件
class Button extends React.PureComponent {

  render() {
    console.log('================')
    return (
      <button onClick={this.props.handleClick}>hahaha</button>
    )
  }

}


//父組件
class ButtonList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      index: -1,
      list: [1, 2, 3, 4]
    };
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick() {
    console.log('Click');
  }
  
  onStateChange = () => {
    this.setState({
      index: 1
    });
  }
  
  render() {
    return (
      <div>
        <button onClick={this.onStateChange}>stateChange</button>   
        {
          this.state.list.map(item => <Button handleClick={this.handleClick}/>)
        }
      </div>
    )
  }
}


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

事件處理中傳參

  在開發當中,常常遇到對一個列表作操做,可能包含刪除,修改,查看。這時候綁定事件就須要傳參,一般爲id。babel

直接傳遞參數

//render中使用箭頭函數
  {
    this.state.list.map(item => (
      <Button onClick={() => this.handleClick(item.id)}/>
    ))
  }
//render中使用bind
  {
    this.state.list.map(item => (
      <Button onClick={this.handleClick.bind(this, item.id)}/>
    ))
  }

使用data屬性

//handleClick中經過e.target.dataset.id獲取
  {
    this.state.list.map(item => (
      <Button data-id={item.id} onClick={this.handleClick}/>
    ))
  }

總結

  這裏不強制推薦使用哪種,對於各個團隊來講,能夠根據項目,選擇本身團隊的事件綁定方式。框架

  由於箭頭函數的簡潔性,在公司項目中,咱們團隊一般使用class fields 定義箭頭函數來綁定事件。
  當須要傳參的時,單個參數傳遞使用data屬性傳參。
  多個參數傳遞時,採用拆分子組件的方式回調傳參。函數

//子組件
class Button extends React.PureComponent {

  handleClick = () => {
    this.props.handleClick(this.props.item);
  }

  render() {
    return (
      <button onClick={this.handleClick}>hahaha</button>
    )
  }
}


//父組件
class ButtonList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [1, 2, 3, 4]
    };
  }
  
  handleClick = (item) => {
    console.log('Click', item);
  }
  
  render() {
    const { list=[] } = this.state;

    return (
      <div>
        {
          list.map(item => <Button handleClick={this.handleClick} item={item}/>)
        }
      </div>
    )
  }
}

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

結語

  前端發展巨快,各類新特性,新框架,新UI層出不窮。須要咱們不斷保持學習,深挖技術底層,這樣遇到任何新的技術,纔可以以一法破萬法。性能

相關文章
相關標籤/搜索