1. 程式人生 > >React事件處理的三種方式及this問題

React事件處理的三種方式及this問題

一,在React元素繫結事件要注意的兩點

      1,在React中事件的命名採用駝峰命名法,而不是原生dom中的小寫,如:onclick要寫成onClick,onchange要寫成onChange

        2,響應事件的函式要以物件的形式賦值,而不是以dom字串的形式,如:

        在dom中:

     <button onclick=“clickMe()”>不服點我</button>

        React中:

      <button onClick={clickButton}>不服點我</button>  //clickButton是一個函式

注:React中的事件是合成事件,並不是dom的原生事件,在dom中可以通過放回false來阻止事件的預設行為,但在react中必須顯示的呼叫事件物件e.preventDefault來阻止事件的預設行為,除了這有點外和原生dom事件並無差別

二,在React中事件處理函式主要的三種寫法方式,不同的寫法解決this指向問題的方式也不同,效能也有差異 ,具體如下:

     1,使用es6的箭頭函式

class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={number:0}

}

       render(){

       <button onClcik={(event)=>{console.log(this.state.number);}}>點我</button>

}

}

此時this指向的是函式定義是的物件,所以this總是指向當前元件的實列,不足是當元件的邏輯比較複雜時,把元件的邏輯寫在{}內會導致render函式變得臃腫,不容易比較直觀的看出ui的結構,同時代碼的可讀性也不是很好,解決方法為把邏輯封裝為元件的一個方法,然後在函式中呼叫這個方法,如下:

  class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={number:0}

}

    handleClcik(event){

     const number=++this.state.number;

    this.setState={

    number

}

}

       render(){

       <button onClcik={(event)=>{this.handleClick(event);}}>點我</button>

}

}

注:直接在render方法中定義事件處理函式的最大問題是,每次render呼叫時都會建立一個新的事件處理函式,給元件帶來額外的開銷,當元件的層級越低,開銷就越大,元件的任何上一層級元件的變化都會觸發這個元件的render方法(一般可以忽略)。

  2,使用元件的方法

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

class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={number:0};

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

}

    handleClcik(event){

     const number=++this.state.number;

    this.setState={

    number

}

}

       render(){

    <div>{this.state.number}</div>

      <button onClcik={this.handleClick}>點我</button>

}

}

注:這種方法的好處是每次render渲染都不會重新建立一個回撥函式,沒有額外的效能損失,但是如果在一個元件中有很多的事件函式時這種在建構函式中繫結this的方法會顯得繁瑣,還可以直接在給事件屬性直接賦值時繫結this;

class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={number:0};

}

    handleClcik(event){

     const number=++this.state.number;

    this.setState={

 number

}

}

       render(){

    <div>{this.state.number}</div>

  {/*事件屬性賦值和this繫結同時*/}

      <button onClcik={this.handleClick.bind(this)}>點我</button>

}

}

但是此方法在每次render時都會重新建立一個新的函式,效能有一定的損失,但在事件處理函式需要傳引數是,這種方法就比較好,如下:

class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={

      list:[1,2,3,4,5],

     current:1

};

}

//每點選一項時,將點選項設定為當前選中項,因此需要將點選項作為引數傳遞

    handleClcik(item,event){

    this.setState={

    current:item

}

}

       render(){

         <ul>

          {

       {/*bind除了繫結this,還繫結item作為引數,供handleClick使用*/}

          this.state.list.map((item)=>(

          <li className={this.state.current==item?"current":""} onClick={this.handleClick.bind(this,item)}>{item}</li>

))

}

</ul>

}

3.屬性初始化語法(property initializer syntax)

使用es7的property initializers 會自動為class中定義的方法繫結this,列如:

class MyComponent extends React.Component{

      constructor(props){

       super(props);

      this.setState={number:0};

}

    handleClcik=(event)=>{

     const number=++this.state.number;

    this.setState={

 number

}

}

       render(){

    <div>{this.state.number}</div>

  {/*事件屬性賦值和this繫結同時*/}

      <button onClcik={this.handleClick}>點我</button>

}

}

此種方法既不需要再建構函式中繫結this,也不需要擔心重複渲染導致重複建立的問題,但:

property initializers還處在實驗性階段,預設不支援,不過官方的腳手架create-react-app預設支援這個特性,如果你想要在你的專案中使用這個預設的特性,你可以在專案中引入babel的transform-class-properties外掛獲取這個特性的支援。

以上為react事件處理的三種方式及this問題的全部內容,如下不當之處歡迎拍正。。。。