react隨筆5 事件處理

事件處理

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

  • React事件綁定屬性的命名采用駝峰式寫法,而不是小寫(DOM元素寫法)。
  • 如果采用了JSX的語法,需要傳入一個函數(shù)作為事件處理函數(shù),而不是一個字符串(DOM元素寫法)
    比如:傳統(tǒng)的HTML:
<button onclick="activateLasers()">Activate Lasers</button>

React中寫法:

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

可以看到,傳統(tǒng)HTML中點擊事件的屬性名是小寫的onclick,而React中是駝峰式的onClick;點擊事件的值,傳統(tǒng)的HTML中是一個字符串,字符串的值就是處理函數(shù)的名稱:activateLasers(),而React中采用的JSX語法,點擊事件的值就是這個函數(shù)名稱:activateLasers

  • React(從版本v0.14開始)中不能使用返回false的方式組織默認行為。必須使用事件的preventDefault函數(shù),傳統(tǒng)的HTML就可以直接返回false。
    比如,傳統(tǒng)的HTML組織鏈接默認打開一個新頁面:
<a   onclick="console.log('The line was clicked');return false">
Click me </a>

這樣點擊鏈接Click me時,會在控制臺輸出The line was clicked,但是不會打開新的url地址https://react.docschina.org/docs/handling-events.html
在React中,直接返回false是不行的。需要顯示調(diào)用出發(fā)事件的preventDefault函數(shù):

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The line was clicked');
  }
  
  return (
    <a  onClick=  
            {handleClick} >Click me </a>
  );
}

ReactDOM.render(
  <ActionLink />, document.getElementById('root')
);

這里是使用函數(shù)式組件演示的,可以直接拷貝代碼在這里測試。記得把上邊的代碼copy到JS框中,如下圖:

image.png

上面是React使用函數(shù)組件來實現(xiàn)的,如果使用類組件,則如下:

class ActionLink extends React.Component {
   constructor(props) {
     super(props);
     this.handleClick = this.handleClick.bind(this);
   }
  
   handleClick(e) {
     e.preventDefault();
     console.log('The line was clicked');
   }
  
  render () { 
    return (<a  onClick={this.handleClick}>Click me </a>);
  };
}
ReactDOM.render(
  <ActionLink />, document.getElementById('root')
); 

結(jié)果如下:


image.png

在這里,e是一個合成事件。React根據(jù)W3C spce來定義這些合成事件。更多事件參考SyntheticEvent 。
使用React的時候通常不需要為DOM元素添加監(jiān)聽器,如使用addEventListener方法。僅僅需要在元素初始化的時候提供一個監(jiān)聽器。
我們也看到了,使用函數(shù)組件和類組件,事件處理函數(shù)在語法上有點區(qū)別。使用函數(shù)組件的時候,事件處理函數(shù)還是像普通的函數(shù)一樣聲明function handleClick() {},但是使用類組件的時候,時間處理函數(shù)就是類的一個方法,所以在定義的時候是handleClick(){},沒有使用function關(guān)鍵字了。
我們還發(fā)現(xiàn),在使用類組件的時候,在構(gòu)造函數(shù)中有這么一句代碼:

this.handleClick = this.handleClick.bind(this);

在render方法的返回元素中,onClick屬性的值,我們使用的是JSX語法:onClic={this.handleClick},也就是點擊事件的處理函數(shù)是this的handleClick方法,this代表的是當前組件。也就是點擊事件其實是回調(diào)的this的handleClick方法,我們必須謹慎對待JSX回調(diào)函數(shù)中的this,類的方法默認是不會綁定this的,如果沒有如上的綁定代碼,即沒有綁定this.handleClick,那么在handleClick這個方法中使用this的話,就會報錯,this提示是undefined:如下:

image.png

這并不是React的特殊行為,他是函數(shù)如何在JavaScript中運行的一部分。如果沒有在方法后面添加(),例如onClick={this.handleClick},那就需要在constructor方法中為handleClick這個方法綁定this。當然可以在后邊機上(),但是這樣在初始化的時候就直接執(zhí)行了,達不到我們想要的效果,圖下圖:
image.png

如果不想使用綁定,還有另外兩種解決方式:

  • 1.使用實驗性的屬性初始化器語法
class ActionLink extends React.Component {
  handleClick = () => {
    console.log(this);
  }

  render() {
    return (<a href="#" onClick={this.handleClick}>click me</a>);
  }
}

如下圖:


image.png
  • 2.在回調(diào)函數(shù)中使用箭頭函數(shù)
class ActionLink extends React.Component{
  handleClick(e) {
    console.log(e);
    console.log(this);
  }
  
  render(){
    return (<a href="#" onClick={(e) => this.handleClick(e)}></a>);
  }
}

如下圖:

image.png

注意:使用這個語法有個問題,每次組件有變化需要重新渲染的時候,都會創(chuàng)建一個不同的回調(diào)函數(shù)。在多數(shù)情況下,沒有問題。但是如果這個回調(diào)函數(shù)作為一個屬性值傳入低階組件,那么這些組件可能會進行額外的重新渲染。

向事件處理程序傳遞參數(shù)

通常我們會給事件處理程序傳遞額外的參數(shù),進行不同的操作。例如,若是id是我們需要刪除的那一行數(shù)據(jù)的id,那么以下兩種穿殘方式度可以:

<a onClick={(e) => this.handleClick(id, e)}>Delete Row</a>
<a onClick={this.handleClick.bind(this, id)}> Delete Row</a>

上述兩種方法是等價的。但是需要注意的是,在使用箭頭函數(shù)arrow functions的形式進行回調(diào)的時候,參數(shù)e作為React時間對象是作為第二個參數(shù)進行傳遞的,也就是時間獨享必須顯示的進行傳遞。但是通過bind的方式,事件對象以及更多的參數(shù)是被隱式的進行傳遞的。
但是通過bind方式向時間處理程序傳遞參數(shù)的時候,如果在事件處理程序中使用到了事件對象本身e,那么在函數(shù)定義的時候,e必須是作為參數(shù)列表的最后一個參數(shù):

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  onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容