export default用法vue_Vue组件通信—provide/inject
前言:
之前在 Vue 中進(jìn)行組件通信一般都會(huì)使用 props,開始使用 provide/inject 是非常偶然的一次嘗試。
當(dāng)時(shí)在開發(fā)中需要實(shí)現(xiàn)祖孫組件,甚至祖祖祖祖孫組件之間的通信,在這種多層級(jí)場景下,props 就顯得太過累贅了,由于是進(jìn)行設(shè)計(jì)器(插件)開發(fā),為了提高插件的可復(fù)用性,減少不必要的包依賴,傾向于在不引入 Vuex 的情況下解決這個(gè)問題,那么就應(yīng)該看看 vue 本身,是否具有這種能力,就在這個(gè)時(shí)候,我發(fā)現(xiàn)了 provide/inject。
官方定義
我們先來看看 Vue 官方的定義是什么:
provide/inject 是 Vue 在 2.2.0 版本新增的 API,官網(wǎng)這段定義看起來好像有點(diǎn)難理解,通俗的講,就是 provide 可以在祖先組件中指定我們想要提供給后代組件的數(shù)據(jù)或方法,而在任何后代組件中,我們都可以使用 inject 來接收 provide 提供的數(shù)據(jù)或方法。
舉個(gè)
// 父級(jí)組件提供 'foo' <template><div><div>{{foo}}</div><son></son></div> </template><script> import Son from "./Son"; export default {name: "parent",components: { Son },provide() {return {foo: this.foo};},data() {return {foo: "測試",};},mounted() {console.log(this.foo)}, }; </script>//子級(jí)組件,不接收 <template><grandSon></grandSon> </template><script> import grandSon from "./grandSon"; export default {name: "son",components: { grandSon }, }; </script>//孫級(jí)組件,接收foo <template><div>{{foo}}</div> </template><script> export default {name: "grandSon",inject: ["foo"],mounted() {console.log(this.foo)}, }; </script>在這里我們可以發(fā)現(xiàn)孫組件越過子組件接收了父組件注入的數(shù)據(jù),我們可以理解為爺爺越過爸爸偷偷給孫子買了冰激凌,這是一組最簡單的用法,當(dāng)層級(jí)繼續(xù)增加時(shí),仍可通過這種方式由父組件直接跨域多個(gè)層級(jí)向后代組件注入數(shù)據(jù)。
有一點(diǎn)需要特別注意的是,實(shí)際上我們可以將當(dāng)前組件inject獲取的數(shù)據(jù)直接賦值給它本身的data或props,不過官網(wǎng)提示我們,這是在Vue2.2.1版本才實(shí)現(xiàn)的功能,在這之前,必須先進(jìn)行props和data數(shù)據(jù)的初始化。
響應(yīng)更新
在嘗試中我們發(fā)現(xiàn),由于Vue的單向流關(guān)系,實(shí)際上如果在parent中改變了初始傳入的foo的值以后,grandSon并不會(huì)得到改變后的值,也就是在這個(gè)時(shí)候,父孫組件的數(shù)據(jù)出現(xiàn)了不一致的情況,我們肯定是希望拿到的數(shù)據(jù)是一致的,怎么來解決這個(gè)問題呢,官網(wǎng)還有一句提示為我們提供了解釋。
提示:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽的對象,那么其對象的 property 還是可響應(yīng)的。 也就是指,我們需要人為的將這組數(shù)據(jù)關(guān)系變成可響應(yīng)的,哦,我們之前的foo是一個(gè)字符串,基本數(shù)據(jù)類型是不具有響應(yīng)特性的,那么,我們可能需要傳遞一個(gè)對象。再舉個(gè)
// 改造一下父級(jí)組件提供 'foo' <template><div><div>{{foo}}</div><son></son></div> </template><script> import Son from "./Son"; export default {name: "parent",components: { Son },provide() {return {foo: this.foo};},data() {return {foo: {foo: "測試"},,};},mounted() {console.log(this.foo)}, }; </script>在這個(gè)栗子中,改造了一下父組件提供的數(shù)據(jù),測試發(fā)現(xiàn),foo變成了一組可響應(yīng)的數(shù)據(jù)。經(jīng)過嘗試我發(fā)現(xiàn)在這種情況下如果在孫組件改變inject中foo的值,也會(huì)響應(yīng)的更新到父組件中,當(dāng)然為了保護(hù)單向數(shù)據(jù)流機(jī)制,最佳實(shí)踐還是不要在子組件里更改inject(雖然 sync 也破壞了單向數(shù)據(jù)流)。
默認(rèn)值設(shè)置
在 2.5.0+ 的注入可以通過設(shè)置默認(rèn)值使其變成可選項(xiàng)<script> export default {name: "grandSon",inject: {foo: {from: 'bar',default: () => [1, 2, 3]}},mounted() {console.log(this.foo)}, }; </script>:在2.5.0 版本之后的版本中可以為inject提供默認(rèn)值了,如果它需要從一個(gè)不同名字的 property 注入,則使用 from 來表示其源 property,與 prop 的默認(rèn)值類似,需要對非原始值使用一個(gè)工廠方法。
呱唧呱唧,那基本用法我們就講到這里了,歸根結(jié)底,既然provide/inject 這么方便,為什么 Vue 官方還要推薦我們使用 Vuex進(jìn)行數(shù)據(jù)管理呢?
明顯的缺點(diǎn)
provide/inject 的缺點(diǎn)還是非常明顯的:
- 當(dāng)多個(gè)后代組件同時(shí)依賴同一個(gè)父組件提供數(shù)據(jù)時(shí),只要任一組件對數(shù)據(jù)進(jìn)行了修改,所有依賴的組件都會(huì)受到影響,實(shí)際上是增加了耦合度。
- 任意層級(jí)訪問使數(shù)據(jù)追蹤變的比較困難,你并不能準(zhǔn)確的定位到是哪一個(gè)層級(jí)對數(shù)據(jù)進(jìn)行了改變,當(dāng)數(shù)據(jù)出現(xiàn)問題時(shí),尤其是多人協(xié)作時(shí),可能會(huì)大大增加問題定位的損耗。
值得肯定的優(yōu)點(diǎn)
萬事萬物都有把雙刃劍,有缺點(diǎn)自然也有優(yōu)點(diǎn),在進(jìn)行組件庫或高級(jí)插件開發(fā)時(shí),provide/inject 仍然是一個(gè)不錯(cuò)的選擇。
留坑待補(bǔ)(應(yīng)當(dāng)不會(huì)鴿)
- 從Vue生命周期源碼來看provide/inject的執(zhí)行過程
- 插件/組件庫應(yīng)用實(shí)例(同樣的功能實(shí)現(xiàn)與Vuex進(jìn)行對比)
最后
其實(shí)之前的筆記都是寫給自己看的,這還是真正意義上的第一篇熱乎乎的博客,emmm感覺還有些地方?jīng)]有講的很明白,也還留坑了一些內(nèi)容后續(xù)會(huì)慢慢完善,輸出真是不易的過程,不過會(huì)繼續(xù)努力學(xué)習(xí)提高噠,有問題歡迎指出,會(huì)及時(shí)更正,奧里給!
最后的最后
給我們的小組賣個(gè)安利,組內(nèi)都是可愛的程序媛小姐姐哦,歡迎熱愛前端的小姐妹們加入我們,一起學(xué)習(xí),共同進(jìn)步【有意請留言或私信,社畜搬磚不及時(shí),但看到會(huì)立刻回復(fù)】總結(jié)
以上是生活随笔為你收集整理的export default用法vue_Vue组件通信—provide/inject的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android蓝牙查看电池容量_双麦降噪
- 下一篇: codelite14中文语言包_Code