provide/inject是什么
依賴注入,官網(wǎng)的描述并不能阻止我不寫(xiě)這個(gè)文章,原因很簡(jiǎn)單,官網(wǎng)只是老菜鳥(niǎo)的隨手備忘錄,小菜鳥(niǎo)還需要成長(zhǎng)磨礪,它不能解決我一些問(wèn)題。
何時(shí)使用
父子組件交互方式多種,props、vuex、$refs、$emit、localStorage還有就是這個(gè)provide/inject了。它適合層級(jí)比較深的組件,比如子,子孫,子孫后代的組件有好幾個(gè)用到父組件的某個(gè)屬性,就可以用到這個(gè)provide/inject,它可以避免寫(xiě)大量繁瑣的傳值代碼
我這里為什么要使用它? 我一個(gè)知識(shí)庫(kù)詳情父組件中包含了大量的子組件,每個(gè)子組件都需要父組件的知識(shí)庫(kù)ID,這時(shí)候我不想寫(xiě)大量props,就用到provide/inject進(jìn)行傳值了
響應(yīng)式傳值最終版
急躁的改寫(xiě)這個(gè)代碼結(jié)構(gòu)就可以完成provide/inject響應(yīng)傳值
data(){return{knowledge: {knowledgeId:''}? ? ? }? ? },
provide(){return{// 直接傳對(duì)象kData:this.knowledge? ? ? }? ? },
created(){// 變更data屬性knowledge下的knowledgeId元素值
this.knowledge.knowledgeId =2
}
子組件使用
inject: ['kData'],
mounted(){console.error('yc:'+this.kData.knowledgeId)? ? }
坑在哪
坑在于provide,子組件inject沒(méi)什么難度
第一版嘗試
下面代碼并不能在子組件獲取這個(gè)kId的值,但網(wǎng)上有provide: {}這樣定義的寫(xiě)法,他們之所以能夠成功是kId: 'xxx'后面定義的是一個(gè)靜態(tài)的字符串而不是動(dòng)態(tài)的獲取data中的knowledgeId屬性
data() {return{? ? ? ? knowledgeId:1}? ? },??
? provide: {? ? ? kId:this.knowledgeId? ? }
第二版嘗試
上面第一版的問(wèn)題很好解決,網(wǎng)上有另外一種寫(xiě)法就是通過(guò)provide函數(shù)返回一個(gè)對(duì)象,這種是可以獲取到data中的屬性內(nèi)容
data(){return{knowledgeId:1}? ? },
provide(){return{kId:this.knowledgeId? ? ? }? ? }
第三版嘗試
第二版看起來(lái)沒(méi)問(wèn)題,但是如果我要在某個(gè)地方改變這個(gè)data中的knowledgeId屬性,子組件是獲取不到的,怎么解決??http://www.lxweimin.com/p/ae0...,這篇文章提到了:
提示:provide 和 inject
綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽(tīng)的對(duì)象,那么其對(duì)象的屬性還是可響應(yīng)的。
雖然上面講到了本質(zhì),老菜鳥(niǎo)都明白,小菜鳥(niǎo)茫然不解,所以它不能阻止我不寫(xiě)下這篇文章,原因在于它沒(méi)有說(shuō)起這個(gè)可監(jiān)聽(tīng)對(duì)象是怎么個(gè)回事。傳入的對(duì)象是指provide中的對(duì)象還是data的對(duì)象?第三版改寫(xiě)成在provide傳入對(duì)象
data(){return{knowledgeId:''}? ? },
provide(){return{pData: {kId:this.knowledgeId? ? ? ? }? ? ? }? ? },
mounted(){
// 更改data中的knowledgeId的值
this.knowledgeId =2
}
第四版嘗試
第三版的寫(xiě)法在子組件中是無(wú)法獲取變更后的knowledgeId的內(nèi)容,那么就在data中包裝一個(gè)對(duì)象,但是還是不行,第五版改寫(xiě)馬上開(kāi)始
data(){return{knowledge: {knowledgeId:''}? ? ? }? ? },
provide(){return{kId:this.knowledge.knowledgeId? ? ? }? ? },
mounted(){this.knowledge.knowledgeId =2}
第五版嘗試
很高興的說(shuō),這版就是終結(jié)版,它可以在子組件獲取到knowledgeId了,原理是什么? 誰(shuí)在乎呢,用別人的工具,用的開(kāi)心就好
data(){return{knowledge: {knowledgeId:''}? ? ? }? ? },
provide(){return{// 直接傳對(duì)象kData:this.knowledge? ? ? }? ? },
mounted(){this.knowledge.knowledgeId =2}
存在的小問(wèn)題
正如文章:http://www.lxweimin.com/p/ae0...?第三點(diǎn)提到的,執(zhí)行順序的問(wèn)題,上面在mounted中處理provide的數(shù)據(jù)有時(shí)會(huì)導(dǎo)致子組件獲取到的是父屬性knowledge.knowledgeId的默認(rèn)屬性'',所以把provide數(shù)據(jù)生成的處理邏輯放到created里面就可以避免這個(gè)問(wèn)題的發(fā)生
題外話
上面變更knowledgId采用了從路由獲取參數(shù),但刷新頁(yè)面導(dǎo)致參數(shù)丟失,這是因?yàn)槁酚墒牵?/p>
path: 'detail'而不是path: 'detail/:knowledgeId',雖然前者通過(guò)
this.$router.push({ name: 'knowledgeDetail', params: { knowledgeId: knowledgeId } }) 也能傳,但刷新就參數(shù)丟失了,同時(shí)webstorm更改后時(shí)不時(shí)抽筋不立即更新頁(yè)面,只能手動(dòng)刪除html樣式來(lái)告訴IDE更新,這些無(wú)疑加大了對(duì)provide/inject剛才是出問(wèn)題的排查難度,索性寫(xiě)下這篇文章指引那些用別人工具還用這么辛苦,寫(xiě)尼瑪代碼的人找到出路
mounted() {? ? ? this.knowledge.knowledgeId= this.$route.params.knowledgeId}