React學習手記3-事件處理

雨田666發表於2019-03-02

事件繫結

React 元素的事件處理和 DOM元素的很相似。但是有一點語法上的不同:

  1. React事件繫結屬性的命名採用駝峰式寫法,而不是小寫。
  2. 如果採用 JSX 的語法你需要傳入一個函式作為事件處理函式,而不是一個字串(DOM元素的寫法)
  3. 阻止事件預設行為只能呼叫e.preventDefault;  而DOM事件還可以使用  return false

例如:

 傳統dom事件

<button onclick="activateLasers()">
  Activate Lasers
</button>

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

React事件

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


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

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

this指向

JSX 中事件繫結的回撥函式中,this並不會指向React元件例項。儘管ES6規範中,class類的方法中,this預設指向類的例項,單如果單獨使用該方法,this會指向函式呼叫的上下文。jsx中事件繫結函式,就是單獨使用,this並不會指向組建的例項。如何繫結this到元件例項,有如下幾種方法:

1. 使用箭頭函式,直接在React元素中採用箭頭函式定義事件的處理函式,如下:

<button onClick={(e) => {console.log(this.state.number)}}> 點選 </button>複製程式碼

因為箭頭函式中this指向的是函式定義是的物件,故保證this總是指向當前元件的例項物件。

但是如果事件處理邏輯較多,這樣直接在元素上寫,造成程式碼可讀性差,故一般把邏輯封裝成元件的一個方法,然後在箭頭函式中呼叫這個方法。

handleClick(event) {
    this.setState({})
}

render(){
    return <button onClick={(e) => {this.handleClick(event)}}> 點選 </button>}複製程式碼

缺點: 直接在render方法中為元素事件定義事件處理函式,每次render呼叫,都會重新建立一個新的事件處理函式。

2.  使用元件的方法,直接將元件方法賦值給元素的事件屬性,同時在類的建構函式中,將這個方法的this繫結到當前物件,如:

class Header extends React.componet {
    constructor (props) {
        super (props)
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick() { }
    render() {
        return <button onClick={this.handleClick}> 點選 </button>
     }   
複製程式碼

3. 還是使用元件的方法,不過是在給元素的時間屬性賦值的時候,同時為時間處理函式繫結this,如果需要向處理函式傳遞額外的引數,這種方式很方便

handleClick(number, event) { 
}
render() {
   return <button onClick={this.handleClick.bind(this,3)}> 點選 </button>
 }   
複製程式碼

4. ES7的屬性初始化語法,自動為class中定義的方法繫結this,如:

handleClick = (event) => { 
}
render() {
   return <button onClick={this.handleClick}> 點選 </button>
 }  複製程式碼

參考阮一峰es6書中,19.14.1小節,應該也算是Class的例項屬性新的寫法

class Myclass {
    myprop = 42;
    consturctor() {
        this.name = "killer"
    }
}複製程式碼

myprop 和 name 都是例項的屬性,只是寫法不一樣

5. ES新提案語法--雙冒號語法,不能帶引數

  bind5(){
    console.log('bind5', this)
  }

 render() {
   return (
    <div>
       <button onClick={::this.bind5}></button>
    </div>
  )
 }複製程式碼

傳參

通常我們會為事件處理程式傳遞額外的引數。例如,若是 id 是你要刪除那一行的 id,以下兩種方式都可以向事件處理程式傳遞引數:

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

引數 e 作為 React 事件物件將會被作為第二個引數進行傳遞。通過箭頭函式的方式,事件物件必須顯式的進行傳遞,但是通過 bind 的方式,事件物件以及更多的引數將會被隱式的進行傳遞。

值得注意的是,通過 bind 方式向監聽函式傳參,在類元件中定義的監聽函式,事件物件 e 要排在所傳遞引數的後面,例如:

class Popper extends React.Component{
    constructor(){
        super();
        this.state = {name:'Hello world!'};
    }
    
    preventPop(name, e){    //事件物件e要放在最後
        e.preventDefault();
        alert(name);
    }
    
    render(){
        return (
            <div>
                <p>hello</p>
                {/* Pass params via bind() method. */}
                <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}複製程式碼

參考 : https://react.docschina.org/docs/handling-events.html


相關文章