1. 程式人生 > 實用技巧 >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中進行優化。

//僅作為示例程式碼,不遵循常用程式碼規範
//子元件
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')
);

1

事件處理中傳參

在開發當中,經常遇到對一個列表做操作,可能包含刪除,修改,檢視。這時候繫結事件就需要傳參,通常為id。

直接傳遞引數

  //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}/>
    ))
  }

資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com

總結

這裡不強制推薦使用哪一種,對於各個團隊來說,可以根據專案,選擇自己團隊的事件繫結方式。

因為箭頭函式的簡潔性,在公司專案中,我們團隊通常使用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')
);