react-事件處理中的this

當你使用 ES6 class 語法定義一個組件的時候,通常的做法是將事件處理函數聲明爲 class 中的方法。例如,下面的 Toggle 組件會渲染一個讓用戶切換開關狀態的按鈕:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>事件處理中this</title>
  <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
  <!-- <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> -->
  <!-- <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script> 
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    class Toggle extends React.Component {
      constructor(props) {
        super(props)
        this.state = { isToggleOn: false }
      }

      handleClick() {
        console.log(this) // undefined
        this.setState((state, props) => ({
          isToggleOn: !state.isToggleOn
        })) 
        // 大括號外需要加小括號
        // 原因:因爲箭頭函數寫法()=>{}後面的大括號作爲函數體,
        // 如果上面(state, props) => {isToggleOn: !state.isToggleOn}不加上()則大括號裏面isToggleOn: !state.isToggleOn將作爲函數體執行,明顯裏面內容不是執行語句。
        // 如果加上小括號,(state, props) => ({isToggleOn: !state.isToggleOn})的函數體就相當於返回一個{isToggleOn: !state.isToggleOn}對象
      }

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

    ReactDOM.render(
      <Toggle />,
      document.getElementById('root')
    )
  </script>
</body>
</html>

當瀏覽器執行上述腳本代碼時會發生如下錯誤:
2.png
錯誤產生的原因是因爲onClick={this.handleClick}僅僅傳入了函數的引用,並沒有綁定執行函數this指向,所以this值是undefinedthis.setState就找不到setState

既然沒有綁定函數的this指向,我們有以下兩種方式指定this

  • 1、使用bind綁定this
constructor(props) {
    super(props)
    this.state = { isToggleOn: false }
    this.handleClick = this.handleClick.bind(this)
}

或者

render() {
    return (
      <button onClick={this.handleClick.bind(this)}>
        {this.state.isToggleOn ? 'on' : 'off'}
      </button>
    )
}
  • 2、回調函數採用調用式
render() {
    return (
      <button onClick={() => this.handleClick()}>
        {this.state.isToggleOn ? 'on' : 'off'}
      </button>
    )
}

handleClick函數調用者是this(Toggle對象),所以函數內部this也指向Toggle對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章