【React整理系列】事件處理

一、React事件命名

不同於Vue,React的事件處理機制更加接近於原生事件的寫法、

對於事件類型的指定,基本上是採用原生的寫法(但是具體事件回調函數的指定有所不同):

<button onClick={activateLasers}>  Activate Lasers
</button>

即使用on+大寫事件類型的形式

二、React事件參數:event對象

React中會默認傳入event對象,這個event對象遵循W3C規範(也就是原生類似)

三、React阻止html元素的默認行爲

在原生JavaScript中,如果要阻止元素的默認行爲(比如說點擊a標籤默認打開鏈接),是在回調函數的最後return false

但是在React,無法使用此方法,必須調用event對象中的preventDefault方法

比如:

function ActionLink() {
    // 使用閉包指定對應回調函數
    function handleClick(e) {    
      e.preventDefault();    
      console.log('The link was clicked.');  
  }
  	return (
    <a href="#" onClick={handleClick}>      Click me
    </a>
  );
}
四、在class組件和function組件中指定處理函數的通常格式
  • 在class組件中,我們通常將回調函數作爲class對象的成員函數:

比如官方文檔中這段代碼:

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')
);

需要注意的有如下幾點:

  1. 所有的handleClick,在外面使用的時候都必須是以this.handleClick的形式進行調用,表示調用的handleClick是當前class的成員函數.

  2. 由於JavaScript的回調函數機制,class定義的回調方法,在回調的時候,是不綁定this的(也就是說,回調的時候的this,是undefinded),關於這點,我們可以試試添加以下打印函數進行嘗試:

     class Link extends React.Component {
            constructor(props) {
                super(props);
                // 不給回調函數綁定this
                // this.handleClick = this.handleClick.bind(this);
            }
            handleClick(event) {
                //回調時候返回值應該是undefinded
                console.log("不綁定this,進行回調函數的時候:")
                console.log(this);
                // console.log(event);
                event.preventDefault();
                alert("clicked a ");
            };
            render() {
                // 非回調的時候
                console.log("非回調,在類中:")
                console.log(this);
                return (
                    <div>
                        <a href="xgpax.top" onClick={this.handleClick}>aaaa</a>
                    </div>
                );
            }
        }
        ReactDOM.render(<Link />, document.getElementById("app"));
    

​ 顯示結果:

​ 很明顯,我們可以看到回調函數中的this指向爲undefined,所以我們需要給回調函數指定this,而這個指定方法,就是function.bind()方法(指定bind這種方法,其實不推薦使用,下文的推薦也只是一種相對而言)。

​ 有兩種指定方法:

	1. 在調用時指定(不推薦)
<a href="xgpax.top" onClick={this.handleClick.bind(this)}>aaaa</a>
  1. 在constructor時指定(推薦)
constructor(props) {
            super(props);
            // 給回調函數綁定this
            this.handleClick = this.handleClick.bind(this);
        }

而現代化的寫法,我們在第五點中講(由於react hooks,class組件也不是很常用了)

  • 函數式組件的事件綁定機制:
// 函數式事件處理
    function Link() {
        let test = 1;
        function handleClick(event) {
            console.log(event);
            // 嘗試打印test 證明可以使用閉包外的變量
            console.log(test); // 1 打印成功
            // 用來阻止默認事件的觸發
            event.preventDefault();
            alert("clicked a!")
        };
        return (
            <div>
                <a href="xgpax.top" onClick={handleClick}>aaaa</a>
            </div>
        );
    }

在這裏需要看到的是,函數內部沒有this指針,所以沒有上述困擾(由於react hooks,函數式逐漸已經成爲主流)

我們採用閉包的方法來定義回調函數,由於閉包的變量機制,也就不會出現變量指向問題。

五、class組件使用ES6的箭頭函數來綁定事件:

使用 bind 很麻煩,我們可以利用箭頭函數與上層共享this的方法來解決,這裏有兩種方式可以解決:

  1. 在定義事件的回調函數的時候,使用箭頭函數,然後在箭頭函數內部定義要執行的方法(可以指定自己需要指定的參數)

    class LoggingButton extends React.Component {
      handleClick() {
        console.log('this is:', this);
      }
    
      render() {
        // 此語法確保 `handleClick` 內的 `this` 已被綁定。    
          return (      
          <button onClick={() => this.handleClick()}>        Click me
          </button>
        );
      }
    }
    
  2. 將回調函數修改爲箭頭函數的形式,用變量名=()=>{}

    的形式進行定義(create-react-app默認使用這種形式,主流)。

    class LoggingButton extends React.Component {
      // 此語法確保 `handleClick` 內的 `this` 已被綁定。
     handleClick = () => {    
           		console.log('this is:', this);  
            }
      render() {
        return (
          <button onClick={this.handleClick}>
            Click me
          </button>
        );
      }
    }
    
六、react回調函數事件的傳參

顯然,默認的event事件無法解決所需要的所有情景,而使用類似小程序中data-set的形式又不夠現代,且繁瑣。

我們有如下指定方式:

  1. 還是利用es6箭頭函數語法

    <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
    
  2. 利用bind進行傳參

    <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
    

在這兩種情況下,React 的事件對象 e 會被作爲第二個參數傳遞。如果通過箭頭函數的方式,事件對象必須顯式的進行傳遞,而通過 bind 的方式,事件對象以及更多的參數將會被隱式的進行傳遞。

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