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問題的全部內容,如下不當之處歡迎拍正。。。。