[譯]React核心概念5:事件處理

原文連接:reactjs.org/docs/handli…html

事件處理函數

處理React元素的事件與處理DOM元素上的事件十分類似,它們僅有一些語法上的區別。react

  • React事件名採用小駝峯命名規則而不是純小寫
  • 使用JSX須要傳入函數做爲事件處理函數而不是傳入字符串

例如,在HTML上瀏覽器

<button onclick="activateLasers()">
  Activate Lasers
</button>
複製代碼

在React中則略微不一樣bash

<button onClick={activateLasers}>
  Activate Lasers
</button>
複製代碼

React上的另外一個不一樣之處在於你不能返回false去阻止默認行爲,必須顯示地調用preventDefault才能阻止默認行爲。函數

在HTML中,爲了阻止錨點連接默認打開一個新頁面能夠這樣寫:性能

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>
複製代碼

可是在React中,須要這樣寫才能阻止打開新頁面:ui

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}
複製代碼

在這裏,e是一個合成事件。React根據W3C規範來定義這些合成事件,因此無需擔憂瀏覽器的兼容問題。this

使用React時,一般不須要調用addEventListener來爲已建立的DOM元素添加監聽器。取而代之的是在元素被渲染之初提供一個監聽器。spa

當你定義了一個ES6 class組件時,一個經常使用的方法是將事件處理器聲明爲class的一個方法。下面的代碼聲明瞭一個Toggle組件,讓用戶能在ON和OFF兩種狀態之間切換。prototype

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // 這段代碼讓this在回調函數中可以有效
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);
複製代碼

必須謹慎對待JSX回調函數中的this,在Javascript中,class方法是不會默認綁定this的。若是你忘記綁定this.handleClick並將它傳遞給onClick,那麼當這個方法被調用時瀏覽器將沒法識別this,由於此時thisundefined

這不是React特有的特性,這與JavaScript的工做原理相關。一般來講,若是不在方法後面加上(),好比onClick={this.handleClick},咱們就應該綁定它。

若是以爲綁定方法很麻煩,這裏有兩種選擇能夠避免綁定。若是你正在使用實驗性的public class fields語法,你可使用class fields正確綁定回調。

class LoggingButton extends React.Component {
  // 這個語法能夠確保回調函數已經綁定了this
  // 但請注意這是實驗性的語法
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}
複製代碼

這種語法在使用Create React App建立的項目中是可使用的。

若是沒有使用class fields語法,那麼你能夠在回調函數中使用箭頭函數。

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 這段代碼確保了handleClick綁定了this
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}
複製代碼

可是這個語法有一個問題,每當LoggingButton被渲染時都會建立一個不一樣回調函數。在大多數狀況下這是沒有問題的,可是若是這個回調函數做爲props傳遞給子組件時,這些組件可能會作一個額外的從新渲染。因此咱們一般推薦在構造函數中綁定事件或者使用class fields語法來綁定以免此類的性能問題。

向事件處理函數傳遞參數

在循環中咱們一般須要傳遞一個額外的參數給事件處理函數。好比若是id時想要刪除的那一行的id,如下兩種方法均可以將id傳遞給事件處理函數。

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
複製代碼

上面兩行代碼是等價的,只不過度別使用了箭頭函數Function.prototype.bind

在上面的兩個例子中,合成事件e表明了React事件,都做爲第二個參數傳遞給事件處理函數。在箭頭函數中咱們須要顯示地傳遞e,可是使用bind方法,事件對象以及更多的參數都被隱式地傳遞。

相關文章
相關標籤/搜索