react中關(guān)于函數(shù)調(diào)用()與bind this的原因及分析
關(guān)于函數(shù)調(diào)用()與bind this的原因
以下內(nèi)容主要基于onClick的回調(diào)函數(shù)解決方案
官方文檔對(duì)于jsx回調(diào)函數(shù)解釋
- 對(duì)待 JSX 回調(diào)函數(shù)中的 this,在 JavaScript 中,class 的方法默認(rèn)不會(huì)綁定 this。
- 如果你忘記綁定this.handleClick 并把它傳入了 onClick,當(dāng)你調(diào)用這個(gè)函數(shù)的時(shí)候 this 的值為 undefined。
//函數(shù)組件則就是 無(wú)狀態(tài)組件 ?只負(fù)責(zé)數(shù)據(jù)的展示(靜態(tài)) //類(lèi)組件這就是有狀態(tài)組件 ? ? ?負(fù)責(zé)更新ui,讓頁(yè)面動(dòng)起來(lái) //狀態(tài)(state )就是數(shù)據(jù),是組件內(nèi)部的私有數(shù)據(jù),只能在組件內(nèi)部使用 //state的值是對(duì)象,即就是一個(gè)組件內(nèi)部可以擁有多個(gè)數(shù)據(jù) class StateComponent extends React.Component{ ? //使用es6簡(jiǎn)化辦法初始化 ? //state={ ? // ?count:0 ? //} ? ?constructor(props) { ? ? super(props); ? ? this.state = {count: 0}; ? ? this.addClick3 = this.addClick3.bind(this); ? } ? addClick(){ ? ? this.setState({count : this.state.count + 1}); ? } ? addClick2=()=>{ ? ? this.setState({count : this.state.count + 1}); ? } ? addClick3(){ ? ? this.setState({count : this.state.count + 1}); ? } ? render(){ ? ? return( ? ? ? <> ? ? <button onClick={()=>{ ? ? ? this.setState({ ? ? ? ? count: this.state.count+1 ? ? ? }) ? ? }}>有狀態(tài)組件,{this.state.count}</button> ? ? <button onClick={this.addClick.bind(this)} >不使用constructor,使用注釋的es6簡(jiǎn)化寫(xiě)法</button> ? ? <button onClick={()=>this.addClick()} >箭頭函數(shù)使用</button> ? ? <button onClick={this.addClick2} >使用箭頭函數(shù)</button> ? ? <button onClick={this.addClick3} >constructor中進(jìn)行綁定后可使用</button> ? ? </> ? ? ) ? } }
由于初學(xué)js以及react框架,所以對(duì)于jsx插值表達(dá)式中的函數(shù)調(diào)用有些疑問(wèn)
function check(){ }
1、有些插值表達(dá)式調(diào)用函數(shù)不需要使用(),如{check};但是有些地方調(diào)用則需要使用(),如{check()}
2、在使用react中的onClick函數(shù)時(shí),調(diào)用函數(shù)如果函數(shù)內(nèi)部沒(méi)有使用this,則可以直接調(diào)用{check};如果使用了this則需要使用特殊處理,如最頂部的代碼所示。
答1
在界面直接使用jsx插值表達(dá)式,如果是希望直接返回函數(shù)結(jié)果,需要使用{check()};如果不需要直接調(diào)用函數(shù),而是等待某些觸發(fā)條件再調(diào)用函數(shù){check}。這里函數(shù)的()即就是函數(shù)調(diào)用,而函數(shù)名是指向函數(shù)體的指針。
react官網(wǎng)對(duì)于以下問(wèn)題的解答可以很好地看出()的區(qū)別
為什么我的函數(shù)每次組件渲染時(shí)都會(huì)被調(diào)用?
確保你在傳遞一個(gè)函數(shù)給組件時(shí),沒(méi)有調(diào)用這個(gè)函數(shù):
hadleClick(){ ?return <div>hello world</div> ?//函數(shù)體內(nèi)部沒(méi)有使用this }
render() { ? // Wrong: handleClick is called instead of passed as a reference! ? return <button onClick={this.handleClick()}>Click Me</button> }
正確做法是,傳遞函數(shù)本身(不帶括號(hào)):
render() { ? // Correct: handleClick is passed as a reference! ? return <button onClick={this.handleClick}>Click Me</button> }
答2
js本身有一個(gè)特性,如果直接調(diào)用函數(shù),盡管函數(shù)內(nèi)部使用了this也可以正常使用。但是如果函數(shù)內(nèi)容使用了this,但是不是直接調(diào)用這個(gè)函數(shù),則內(nèi)部的this會(huì)丟失,this會(huì)變成undefined。
所以下面代碼中renderList()直接調(diào)用,使用{this.renderList()},盡管函數(shù)體內(nèi)部使用了this,也不需要特殊處理。
但是onClick就不是直接調(diào)用。這里的onClick就相當(dāng)于一個(gè)中間量。
函數(shù)體內(nèi)部的this指向會(huì)丟失。
class Comment extends React.Component{ ? ? state={ ? ? ? ? ?comments:[ ? ? ? ? ? ? {id:1,name:'jack',comment:"沙發(fā)"}, ? ? ? ? ? ? {id:2,name:"tom",comment:'沙發(fā)不錯(cuò)'}, ? ? ? ? ? ? {id:3,name:"blue",comment:"還行"} ? ? ? ? ?] ? ? } ? ? renderList(){ ? ? ? ? return( ? ? ? ? ? ? this.state.comments.kength===0? ? ? ? ? ? ? ? ? <div className="no-comment" >暫無(wú)評(píng)論,快去評(píng)論</div>: ? ? ? ? ? ? ? ? <ul > ? ? ? ? ? ? ? {this.state.comments&&this.state.comments.map(comment=> ? ? ? ? ? ? ? ? ? <li key={comment.id}><h3>評(píng)論人:{comment.name}</h3> ? ? ? ? ? ? ? ? ? <p>評(píng)論內(nèi)容 :{comment.content}</p> ? ? ? ? ? ? ? ? ? </li> ? ? ? ? ? ? ? )}? ? ? ? ? ? ? ? ?</ul> ? ? ? ? ? ? ?? ? ? ? ? ) ? ? } ? ? ? render(){ ? ? ? ? return( ? ? ? ? ? ? <> ? ? ? ? ? ? {this.renderList()} ? ? ? ? ? ? ?</> ? ? ? ? ) ? ? ? } }
this的丟失可以使用箭頭函數(shù)來(lái)解決,因?yàn)榧^函數(shù)具有如下特質(zhì):
箭頭函數(shù)的時(shí)候,箭頭函數(shù)會(huì)默認(rèn)幫我們綁定外層 this 的值,所以在箭頭函數(shù)中 this 的值和外層的 this 是一樣的。
因此可以通過(guò)使用箭頭函數(shù)避免this的丟失,當(dāng)然為了避免this的丟失還有很多種方式
1、使用es5的語(yǔ)法,在初始化component的時(shí)候使用constructor,對(duì)函數(shù)進(jìn)行綁定
2、在中間量聲明時(shí)使用bind(this) 進(jìn)行綁定
3、中間量聲明函數(shù)時(shí)使用箭頭函數(shù),可以直接進(jìn)行函數(shù)調(diào)用;或者將函數(shù)內(nèi)容直接書(shū)寫(xiě)在箭頭函數(shù)內(nèi)(注意這里進(jìn)行函數(shù)調(diào)用時(shí)需要使用函數(shù)名+(),因?yàn)樵诤瘮?shù)內(nèi)部聲明是直接調(diào)用)
4、最常用的方式,使用箭頭函數(shù)聲明函數(shù),則可以直接調(diào)用,不需要額外處理
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
React類(lèi)組件中super()和super(props)的區(qū)別詳解
這篇文章給大家詳細(xì)介紹了React類(lèi)組件中super()和super(props)有什么區(qū)別,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01react實(shí)現(xiàn)todolist的增刪改查詳解
這篇文章主要為大家介紹了react實(shí)現(xiàn)todolist的增刪改查,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12基于CSS實(shí)現(xiàn)MaterialUI按鈕點(diǎn)擊動(dòng)畫(huà)并封裝成 React 組件
筆者先后開(kāi)發(fā)過(guò)基于vue,react,angular等框架的項(xiàng)目,碧如vue生態(tài)的elementUI, ant-design-vue, iView等成熟的UI框架, react生態(tài)的ant-design, materialUI等,這些第三方UI框架極大的降低了我們開(kāi)發(fā)一個(gè)項(xiàng)目的成本和復(fù)雜度,使開(kāi)發(fā)者更專(zhuān)注于實(shí)現(xiàn)業(yè)務(wù)邏輯和服務(wù)化2021-11-11詳解React-Native全球化多語(yǔ)言切換工具庫(kù)react-native-i18n
這篇文章主要介紹了詳解React-Native全球化語(yǔ)言切換工具庫(kù)react-native-i18n,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11react-router 路由切換動(dòng)畫(huà)的實(shí)現(xiàn)示例
這篇文章主要介紹了react-router 路由切換動(dòng)畫(huà)的實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12編寫(xiě)React組件項(xiàng)目實(shí)踐分析
本文通過(guò)實(shí)例給大家分享了編寫(xiě)React組件項(xiàng)目實(shí)踐的全過(guò)程,對(duì)此有興趣的朋友可以參考下。2018-03-03React和Vue實(shí)現(xiàn)文件下載進(jìn)度條
本文主要介紹了React和Vue實(shí)現(xiàn)文件下載進(jìn)度條,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Electron整合React使用搭建開(kāi)發(fā)環(huán)境的步驟詳解
這篇文章主要介紹了Electron整合React使用搭建開(kāi)發(fā)環(huán)境,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2020-06-06React?高德地圖進(jìn)京證路線規(guī)劃問(wèn)題記錄(匯總)
這篇文章主要介紹了React高德地圖進(jìn)京證路線規(guī)劃問(wèn)題小記,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08