1. 程式人生 > >react入坑之事件

react入坑之事件

1 基本用法

在React中繫結事件跟直接在HTML中繫結事件非常相似,定義一個事件處理函式,並在JSX中繫結它:

function Greeting () {
  function sayHi(e) {
    e.preventDefault()
    console.log('Hi!')
  }
 return (
    <a onClick={Greeting}>Click me to say hi!</a>
 )
}


所有事件繫結屬性比如onClick均使用駝峰寫法(camelCase),事件繫結屬性的值不是字串而是事件處理函式名稱,可以帶上()並傳參,無引數時可省略()

2 使用類定義元件時事件處理函式this的指向問題

使用ES6的class特性定義元件時,通常的做法是將事件處理函式當作該類的方法寫在類中。但需要注意的是方法的this指向。

定義在類中的方法的預設的this指向的是當前的類的例項,但事件處理函式因為是繫結到了具體的元素上,就會丟失定義時this的指向。如果你的處理函式中使用了this關鍵字來指向當前元件例項,那麼你需要手動將該方法的this繫結到當前元件例項,有三種方法可以進行繫結:

1)在類的constructor中呼叫或在JSX中呼叫Function.prototype.bind()手動繫結

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    this.handleClick = this.handleClick.bind(this); // 手動繫結
  }

  handleClick() {
    // console.log(this)
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      // <button onClick={this.handleClick.bind(this)}> // 在這裡繫結也可以
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('content')
);
2)在JSX的事件繫結屬性中的事件處理函式外層再套一個箭頭函式,在其中返回處理函式呼叫結果
render() {
  return (
    <button onClick={(e) => this.handleClick(e)}> // 這麼繫結也行
      Click me
    </button>
  );
}

3)Babel提供的一個ES8+的實驗性質的寫法
class LoggingButton extends React.Component {
  handleClick = () => { // 純粹的實驗性質的寫法,需要babel的支援
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

3 事件物件

React的事件物件是一個完全由React給出的事件物件,該物件對各個瀏覽器做了相容,同時保留了標準事件物件的介面,詳細資訊可以檢視React官網的參考。使用時需要關心的是如何在事件處理函式中使用事件物件。

在事件繫結的JSX中,處理函式接受一個名為event的引數來表示事件物件,可以認為event在事件繫結插值中屬於React的保留字,如果需要往事件處理函式中傳遞更多引數,請使用其他識別符號。

另外,7.2小節中不同的事件繫結寫法也對事件物件的處置略有不同,主要體現在事件繫結JSX中:

// 無括號
<button onClick={this.handleClick}>
  Click me
</button>

// 帶括號
<button onClick={this.handleClick(event)}>
  Click me
</button>

// 呼叫了bind()
<button onClick={this.handleClick.bind(this, event)}>
  Click me
</button>

  • 當事件繫結插值中的處理函式省略了()時,處理函式預設接受一個表示事件物件的引數,
  • 當事件繫結插值中的處理函式未省略()時,則需要顯示地使用保留字event來傳入事件物件,未傳入則為undefined注意,不管有沒有在constructor中繫結this,直接在處理函式名後加()會導致頁面初始化時該函式被立即執行一次,可能會有意想不到的錯誤,比如不能呼叫setState()方法等,所以強烈不建議用這種寫法
  • 當事件繫結插值中的處理函式呼叫了bind()時,可以顯示地使用保留字event來傳入事件物件,否則React會在bind()函式引數序列的末尾預設增加一個表示事件物件的引數

最後,在React中不能通過return false來阻止預設事件,而是需要在事件處理函式中顯式呼叫event.preventDefault()