在react中,處理事件響應(yīng)的方式主要有: (1).?使用匿名函數(shù); (2).使用組件的方法; (3).?使用屬性初始化的語(yǔ)法;?
? ? (1).使用匿名函數(shù),
? ? ? ? 這是最簡(jiǎn)單的一種方式,哪里需要響應(yīng)事件就在哪里創(chuàng)建一個(gè)匿名函數(shù),
先看代碼:?
? handleChange(e){
? ? ? ? console.log("e",e);
? }
render(){
? return? ?<div>
? ? ? ? ? ? ? ? <Button onClick = {(e) => handleChange(e)}></Button>
????????</div>
}
????????點(diǎn)擊Button的事件響應(yīng)函數(shù)是一個(gè)匿名函數(shù)涵紊,這應(yīng)該是最常見(jiàn)的處理事件響應(yīng)的方式了。這種方式的好處是,簡(jiǎn)單直接肴掷。哪里需要處理事件響應(yīng)刨裆,就在哪里定義一個(gè)匿名函數(shù)處理司蔬。
????????在上面的代碼中,也可以不使用箭頭函數(shù),直接使用onClick = {function(){}}的形式,?但實(shí)際開(kāi)發(fā)中不會(huì)用到這種方式,因?yàn)榧^函數(shù)解決了this綁定的問(wèn)題耿战,可以將函數(shù)體內(nèi)的this綁定到當(dāng)前對(duì)象秸脱,而不是運(yùn)行時(shí)調(diào)用函數(shù)的對(duì)象芳绩。如果響應(yīng)函數(shù)中需要使用this.state,那么這種方式就無(wú)法正常運(yùn)行了撞反。所以項(xiàng)目中一般直接使用箭頭函數(shù)定義的匿名函數(shù)作為事件響應(yīng)妥色。
? ??????使用匿名函數(shù)的缺點(diǎn)是:當(dāng)事件響應(yīng)邏輯比較復(fù)雜時(shí),匿名函數(shù)的代碼量會(huì)很大遏片,會(huì)導(dǎo)致render函數(shù)變得臃腫嘹害,不容易直觀地看出組件最終渲染出的元素結(jié)構(gòu)。另外吮便,每次render方法調(diào)用時(shí)笔呀,都會(huì)重新創(chuàng)建一個(gè)匿名函數(shù)對(duì)象,帶來(lái)額外的性能開(kāi)銷(xiāo)髓需,當(dāng)組件的層級(jí)越低時(shí)许师,這種開(kāi)銷(xiāo)就越大,因?yàn)槿魏我粋€(gè)上層組件的變化都可能會(huì)觸發(fā)這個(gè)組件的render方法僚匆。當(dāng)然微渠,在大多數(shù)情況下,這點(diǎn)性能損失是可以不必在意的咧擂。
(2).使用組件方法:
? ? 毫無(wú)疑問(wèn),按鈕的響應(yīng)事件是直接調(diào)用組件的方法,這種方式需要通過(guò)在?constructor中手動(dòng)綁定this;
? ? 看代碼:
? ??constructor(props, context) {
? super(props, context);
? this.state = {
? ? options: {},
? }
? this.handleChange = this.handleChange.bind(this);
}
handleChange (e){
? console.log("e",e);
}
render(){
return <div>
? ? ? ? <button onClick={this.handleChange?}>功能介紹聽(tīng)您的</button>
</div>
}
????????點(diǎn)擊Button的事件響應(yīng)函數(shù)是組件的方法:handleClick逞盆。這種方式的好處是:每次render方法的調(diào)用,不會(huì)重新創(chuàng)建一個(gè)新的事件響應(yīng)函數(shù)松申,沒(méi)有額外的性能損失云芦。但是俯逾,使用這種方式要在構(gòu)造函數(shù)中為作為事件響應(yīng)的方法(handleClick),手動(dòng)綁定this: this.handleClick = this.handleClick.bind(this)舅逸,這是因?yàn)镋S6 語(yǔ)法的緣故桌肴,ES6 Class 的方法默認(rèn)不會(huì)把this綁定到當(dāng)前的實(shí)例對(duì)象上,需要我們手動(dòng)綁定琉历。每次都手動(dòng)綁定this是不是有點(diǎn)繁瑣坠七?好吧,讓我們來(lái)看下一種方式善已。
(3).?使用屬性初始化語(yǔ)法
? ??//代碼4
????class MyComponent extends React.Component{
? ??????state = {number: 0};
? handleClick = () => {
? ? this.setState({
? ? ? number: ++this.state.number
? ? });
? }
? render() {
? ? return (
<button onClick={this.handleClick}>功能介紹聽(tīng)您的</button>
? ? );
? }
}
說(shuō)明: 這里是利用的es7的屬性初始化語(yǔ)法,?從constructor里拿出來(lái)放到property initializer(屬性初始化器)里。我們可以看到這里沒(méi)有使用constructor函數(shù), 直接將state寫(xiě)在了外面.?constructor是ES6中類(lèi)的構(gòu)造函數(shù)离例。整個(gè)構(gòu)造函數(shù)需要一個(gè)參數(shù)props,其全部的值都在上文的代碼中給出:title艘包、image等耀盗。state = ...一句中,使用props初始化了整個(gè)組件的state初值舌厨。
擴(kuò)展:事件響應(yīng)函數(shù)的傳參問(wèn)題
事件響應(yīng)函數(shù)默認(rèn)是會(huì)被傳入一個(gè)事件對(duì)象Event作為參數(shù)的忿薇。如果想傳入其他參數(shù)給響應(yīng)函數(shù)應(yīng)該怎么辦呢?使用第一種方式的話(huà)很簡(jiǎn)單揉燃,直接使用新參數(shù):
//代碼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 (
? ? ? ? {this.state.list.map(
? ? ? ? ? (item)=>(
? ? ? ? ? ? onClick={(event) => this.handleClick(item, event)}>{item}
? ? ? ? ? )
? ? ? ? )}
? ? );
? }
}
onClick的響應(yīng)函數(shù)中筋栋,方法體內(nèi)可以直接使用新的參數(shù)item弊攘。
使用第二種方式的話(huà),可以把綁定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 (
? ? ? ? {this.state.list.map(
? ? ? ? ? (item)=>(
? ? ? ? ? ? onClick={this.handleClick.bind(this, item)}>{item}
? ? ? ? ? )
? ? ? ? )}
? ? );
? }
}
使用第三種方式,解決方案和第二種基本一致:
//代碼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 (
? ? ? ? {this.state.list.map(
? ? ? ? ? (item)=>(
? ? ? ? ? ? onClick={this.handleClick.bind(undefined, item)}>{item}
? ? ? ? ? )
? ? ? ? )}
? ? );
? }
}
????????不過(guò)這種方式就有點(diǎn)雞肋了形纺,因?yàn)殡m然你不需要通過(guò)bind函數(shù)綁定this徒欣,但仍然要使用bind函數(shù)來(lái)綁定其他參數(shù)。
????????關(guān)于事件響應(yīng)函數(shù)脂新,還有一個(gè)地方需要注意粗梭。不管你在響應(yīng)函數(shù)中有沒(méi)有顯式的聲明事件參數(shù)Event,React都會(huì)把事件Event作為參數(shù)傳遞給響應(yīng)函數(shù)滞乙,且參數(shù)Event的位置總是在其他自定義參數(shù)的后面斩启。例如醉锅,在代碼6和代碼7中兔簇,handleClick的參數(shù)中雖然沒(méi)有聲明Event參數(shù)男韧,但你依然可以通過(guò)arguments[1]獲取到事件Event對(duì)象此虑。
????????總結(jié)一下口锭,三種事件處理的方式,第一種有額外的性能損失韭寸;第二種需要手動(dòng)綁定this荆隘,代碼量增多;第三種用到了ES7的特性晶渠,目前并非默認(rèn)支持,需要Babel插件的支持便瑟,但是寫(xiě)法最為簡(jiǎn)潔番川,也不需要手動(dòng)綁定this。一般推薦使用第二種和第三種方式践啄。
參考文檔:? 1.?http://www.reibang.com/p/429b2326bf9b
2.https://www.cnblogs.com/ikcamp/p/8989492.html
3.?官方文檔:http://www.css88.com/react/docs/handling-events.html
4.?https://segmentfault.com/q/1010000007247736/a-1020000007247989