在React中如何優(yōu)雅的處理事件響應(yīng)詳解
前言
本文主要給大家介紹的是關(guān)于React處理事件響應(yīng)的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面來(lái)一起看看詳細(xì)的介紹吧。
React中定義一個(gè)組件,可以通過(guò)React.createClass或者ES6的class。本文討論的React組件是基于class定義的組件。采用class的方式,代碼結(jié)構(gòu)更加清晰,可讀性強(qiáng),而且React官方也推薦使用這種方式定義組件。
處理事件響應(yīng)是Web應(yīng)用中非常重要的一部分。React中,處理事件響應(yīng)的方式有多種。
一、使用箭頭函數(shù)
先上代碼:
//代碼1
class MyComponent extends React.Component {
render() {
return (
<button onClick={()=>{console.log('button clicked');}}>
Click
</button>
);
}
}
當(dāng)事件響應(yīng)邏輯比較復(fù)雜時(shí),再把所有的邏輯直接寫在onClick的大括號(hào)內(nèi),就會(huì)導(dǎo)致render函數(shù)變得臃腫,不容易直觀地看出組件render出的元素結(jié)構(gòu)。這時(shí),可以把邏輯封裝成組件的一個(gè)方法,然后在箭頭函數(shù)中調(diào)用這個(gè)方法。
如下所示:
//代碼2
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {number: 0};
}
handleClick() {
this.setState({
number: ++this.state.number
});
}
render() {
return (
<div>
<div>{this.state.number}</div>
<button onClick={()=>{this.handleClick();}}>
Click
</button>
</div>
);
}
}
這種方式最大的問(wèn)題是,每次render調(diào)用時(shí),都會(huì)重新創(chuàng)建一個(gè)事件的回調(diào)函數(shù),帶來(lái)額外的性能開銷,當(dāng)組件的層級(jí)越低時(shí),這種開銷就越大,因?yàn)槿魏我粋€(gè)上層組件的變化都可能會(huì)觸發(fā)這個(gè)組件的render方法。當(dāng)然,在大多數(shù)情況下,這點(diǎn)性能損失是可以不必在意的。這種方式也有一個(gè)好處,就是不需要考慮this的指向問(wèn)題,因?yàn)檫@種寫法保證箭頭函數(shù)中的this指向的總是當(dāng)前組件。
二、使用組件方法
代碼先:
//代碼3
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {number: 0};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
number: ++this.state.number
});
}
render() {
return (
<div>
<div>{this.state.number}</div>
<button onClick={this.handleClick}>
Click
</button>
</div>
);
}
}
這種方式的好處是每次render,不會(huì)重新創(chuàng)建一個(gè)回調(diào)函數(shù),沒有額外的性能損失。需要注意的是,使用這種方式要在構(gòu)造函數(shù)中為事件回調(diào)函數(shù)綁定this: this.handleClick = this.handleClick.bind(this) ,否則handleClick中的this是undefined。這是因?yàn)镋S6 語(yǔ)法的緣故,ES6 的 Class 構(gòu)造出來(lái)的對(duì)象上的方法默認(rèn)不綁定到 this 上,需要我們手動(dòng)綁定。每次都手動(dòng)綁定this是不是有點(diǎn)蛋疼?好吧,讓我們來(lái)看下一種方式。
三、屬性初始化語(yǔ)法(property initializer syntax)
使用ES7的 property initializers,代碼可以這樣寫:
//代碼4
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {number: 0};
}
handleClick = () => {
this.setState({
number: ++this.state.number
});
}
render() {
return (
<div>
<div>{this.state.number}</div>
<button onClick={this.handleClick}>
Click
</button>
</div>
);
}
}
哈哈,再也不用手動(dòng)綁定this了。但是你需要知道,這個(gè)特性還處于試驗(yàn)階段,默認(rèn)是不支持的。如果你是使用官方腳手架Create React App 創(chuàng)建的應(yīng)用,那么這個(gè)特性是默認(rèn)支持的。你也可以自行在項(xiàng)目中引入babel的transform-class-properties插件獲取這個(gè)特性支持。
四、回調(diào)函數(shù)傳參問(wèn)題
事件的回調(diào)函數(shù)默認(rèn)是會(huì)被傳入一個(gè)事件對(duì)象Event作為參數(shù)的。如果我想傳入其他參數(shù)給回調(diào)函數(shù)應(yīng)該怎么辦呢?
使用第一種方式的話很簡(jiǎn)單,直接傳就可以了:
//代碼5
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [1,2,3,4],
current: 1
};
}
handleClick(item,event) {
this.setState({
current: item
});
}
render() {
return (
<ul>
{this.state.list.map(
(item)=>(
<li className={this.state.current === item ? 'current':''}
onClick={(event) => this.handleClick(item, event)}>{item}
</li>
)
)}
</ul>
);
}
}
使用第二種方式的話,可以把綁定this的操作延遲到render中,在綁定this的同時(shí),綁定額外的參數(shù):
//代碼6
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [1,2,3,4],
current: 1
};
}
handleClick(item) {
this.setState({
current: item
});
}
render() {
return (
<ul>
{this.state.list.map(
(item)=>(
<li className={this.state.current === item ? 'current':''}
onClick={this.handleClick.bind(this, item)}>{item}
</li>
)
)}
</ul>
);
}
}
使用第三種方式,解決方案和第二種基本一致:
//代碼7
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [1,2,3,4],
current: 1
};
}
handleClick = (item) => {
this.setState({
current: item
});
}
render() {
return (
<ul>
{this.state.list.map(
(item)=>(
<li className={this.state.current === item ? 'current':''}
onClick={this.handleClick.bind(undefined, item)}>{item}
</li>
)
)}
</ul>
);
}
}
不過(guò)這種方式就有點(diǎn)雞肋了,因?yàn)殡m然你不需要通過(guò)bind函數(shù)綁定this,但仍然要使用bind函數(shù)來(lái)綁定其他參數(shù)。
關(guān)于事件響應(yīng)的回調(diào)函數(shù),還有一個(gè)地方需要注意。不管你在回調(diào)函數(shù)中有沒有顯式的聲明事件參數(shù)Event,React都會(huì)把事件Event作為參數(shù)傳遞給回調(diào)函數(shù),且參數(shù)Event的位置總是在其他自定義參數(shù)的后面。例如,在代碼6和代碼7中,handleClick的參數(shù)中雖然沒有聲明Event參數(shù),但你依然可以通過(guò)arguments[1]獲取到事件Event對(duì)象。
總結(jié)
三種綁定事件回調(diào)的方式,第一種有額外的性能損失;第二種需要手動(dòng)綁定this,代碼量增多;第三種用到了ES7的特性,目前并非默認(rèn)支持,需要Babel插件的支持,但是寫法最為簡(jiǎn)潔,也不需要手動(dòng)綁定this。推薦使用第二種和第三種方式。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
解決React初始化加載組件會(huì)渲染兩次的問(wèn)題
這篇文章主要介紹了解決React初始化加載組件會(huì)渲染兩次的問(wèn)題,文中有出現(xiàn)這種現(xiàn)象的原因及解決方法,感興趣的同學(xué)跟著小編一起來(lái)看看吧2023-08-08
基于React實(shí)現(xiàn)表單數(shù)據(jù)的添加和刪除詳解
這篇文章主要給大家介紹了基于React實(shí)現(xiàn)表單數(shù)據(jù)的添加和刪除的方法,文中給出了詳細(xì)的示例供大家參考,相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-03-03
解析react?函數(shù)組件輸入卡頓問(wèn)題?usecallback?react.memo
useMemo是一個(gè)react hook,我們可以使用它在組件中包裝函數(shù)??梢允褂盟鼇?lái)確保該函數(shù)中的值僅在依賴項(xiàng)之一發(fā)生變化時(shí)才重新計(jì)算,這篇文章主要介紹了react?函數(shù)組件輸入卡頓問(wèn)題?usecallback?react.memo,需要的朋友可以參考下2022-07-07
React跨路由組件動(dòng)畫實(shí)現(xiàn)
在 React 中路由之前的切換動(dòng)畫可以使用 react-transition-group 來(lái)實(shí)現(xiàn),但對(duì)于不同路由上的組件如何做到動(dòng)畫過(guò)渡是個(gè)很大的難題,目前社區(qū)中也沒有一個(gè)成熟的方案,本文給大家分享React跨路由組件動(dòng)畫實(shí)現(xiàn),感興趣的朋友一起看看吧2023-10-10
詳解react如何實(shí)現(xiàn)復(fù)合組件
在一些react項(xiàng)目開發(fā)中,常常會(huì)出現(xiàn)一些組合的情況出現(xiàn),這篇文章主要為大家介紹了復(fù)合組件的具體實(shí)現(xiàn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
React特征Form?單向數(shù)據(jù)流示例詳解
這篇文章主要為大家介紹了React特征Form?單向數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
React Native react-navigation 導(dǎo)航使用詳解
本篇文章主要介紹了React Native react-navigation 導(dǎo)航使用詳解,詳解的介紹了react-navigation導(dǎo)航的使用,具有一定的參考價(jià)值,有興趣的可以了解一下2017-12-12

