React文檔(七)處理事件


React元素處理事件和DOM元素處理事件很類似。下面是一些語法的不同之處:

  • React事件的命名是用駝峰命名,而不是小寫字母。
  • 利用JSX你傳遞一個函數作為事件處理器,而不是一個字符串。

舉個例子,這是一段HTML:

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

而在React中略微有些不同:

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

另一個不同之處就是在React中你不能通過返回false來阻止事件默認的行為。你必須調用preventDefault。舉個例子,一個簡單的頁面,為了阻止默認的鏈接行為打開一個新頁面,你可以這樣寫:

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

在React中就得這樣寫:

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

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

在這里,e是一個綜合的事件。React通過W3C標准來定義這些綜合事件,所以你可以不用擔心跨瀏覽器兼容性問題。看看SyntheticEvent手冊學習更多知識。

當使用React你通常不需要調用addEventListener來向一個被創建的DOM元素添加事件監聽器。只需要當元素首次被渲染的時候提供一個監聽器。

當你使用ES6的類定義了一個組件,一個相同的模式就是一個事件監聽器會是類的一個方法。舉個例子,這個Toggle組件渲染了一個按鈕來讓用戶在打開和關閉的狀態中來回變化:

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

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  //bind方法會將函數handleClick的this設置為提供的this } handleClick() {
this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } ReactDOM.render( <Toggle />, document.getElementById('root') );

在CodePen中試一試

你必須謹慎對待 JSX 回調函數中的 this,類的方法默認是不會綁定 this 的。如果你忘記綁定 this.handleClick 並把它傳入 onClick, 當你調用這個函數的時候 this 的值會是 undefined。

這並不是React的特殊行為;而是函數如何在js中工作的一部分。通常,如果你涉及到了一個后面沒有()的方法,就像onClick={this.handleClick},你應該為那個函數調用bind方法改變它的this。

如果調用bind使你厭煩,還有兩種方法可以避免使用bind。如果你使用實驗性的屬性初始化語法,你可以使用屬性初始化來正確地綁定回調:

class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.
  handleClick = () => {
    console.log('this is:', this);
  }

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

這個語法在Create React App中默認開啟。

如果你不使用屬性初始化語法,你可以在回調里使用箭頭函數:

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

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}
這個語法的問題就是當LoggingButton組件每一次渲染的時候一個不同的回調函數就會被創建。在大多數情況下,這沒有什么問題。然而,如果這個回調函數被當做一個props傳遞給子組件,那么那些子組件可能會做一次重新渲染。我們通常建議將方法在構造函數里綁定一下this或者使用屬性初始化語法,這樣可以避免這一類重復創建的問題。
向事件處理程序傳遞參數
通常我們會為事件處理程序傳遞額外的參數。例如,若是 id 是你要刪除那一行的 id,以下兩種方式都可以向事件處理程序傳遞參數:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上述兩種方式是等價的,分別通過 arrow functions 和 Function.prototype.bind 來為事件處理函數傳遞參數。

上面兩個例子中,參數 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>
        );
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM