官網(wǎng)傳送門:inject ?Vue2.2.0+
# 背景
? 關于Vue組件的通訊方式相信大家能倒背如流
-
父子組件:通過
prop
,$emit
健提,【$root
雳刺,$parent
,$children
】 -
非父子組件:Vuex實現(xiàn)飒箭,父子層層傳遞轻抱、中央事務總線Bus,
$ref
子實例可以用
this.$parent
訪問父實例衷旅,子實例被推入父實例的$children
數(shù)組中器一。應當節(jié)制地使用它們课锌,其只是作為訪問組件的應急方法。更推薦用 props 和 events 實現(xiàn)父子組件通信.
Vue官網(wǎng)建議祈秕,在正常情況下渺贤,這兩種方式已經(jīng)能滿足絕大多數(shù)甚至所有的業(yè)務需求,對于應用程序代碼應優(yōu)先使用它們處理请毛。然而癣亚,還有一種主要為高階插件/組件庫提供的用例辦法,即provide/inject
获印,這對選項需要一起使用。
?
# 功能
? 通常情況下街州,父組件向孫組件傳遞數(shù)據(jù)兼丰,可以采用父子props
層層傳遞,也可以使用bus
和Vuex
直接交互唆缴。在Vue2.2.0之后鳍征,Vue還提供了provide/inject
選項
這對選項允許一個祖先組件向其所有子孫后代組件注入一個依賴,不論組件層次有多深面徽,并在起上下游關系成立的時間里始終生效艳丛。
? 也就是說,在父組件只要聲明了provide
趟紊,在其子組件氮双,孫組件,曾孫組件等能形成上下游關系的組件中交互霎匈,無論多深都能通過inject
來訪問provider
中的數(shù)據(jù)戴差。而不是局限于只能從當前父組件的prop
屬性來獲取。注意他只做祖先通后代的單向傳遞的一個辦法铛嘱。有人這么形容:
provide就相當于加強版父組件prop暖释,可以跨越中間組件
,inject就相當于加強版子組件的props
?
# 缺點
? 官網(wǎng)不建議在應用中直接使用該辦法墨吓,理由很直接:他怕你"管不好"
? 設計項目球匕,通常追求有清晰的數(shù)據(jù)流向和合理的組件層級關系便于調(diào)試和維護,然而這對選項支持任意層級都能訪問帖烘,導致數(shù)據(jù)追蹤比較困難亮曹。不知道那一層級聲明了provide
又或是哪些層級使用了inject
。造成比較大的維護成本。因此乾忱,除組件庫或高階插件外讥珍,Vue建議用Vuex解決或其他辦法處理。
?
# 使用辦法
-
provide 提供變量:
Object | () => Object
-
inject 注入變量:
Array<string> | { [key: string]: string | Symbol | Object }
? provide
選項應該是一個對象或返回一個對象的函數(shù)窄瘟。 該對象包含可注入其子孫的屬性衷佃。在該對象中,它支持ES6中Symbol
作為key
蹄葱,但只在原生支持等環(huán)境下可工作氏义。
? inject
選項可以是
- 一個字符串數(shù)組
- 一個對象,
key
為本地綁定名图云,value
為:- 在可用的注入內(nèi)容中搜索用的
key
惯悠,或 - 一個對象,其
from
屬性是在可用的注入內(nèi)容中搜索用的key
竣况,default
屬性是降級情況下使用的value
- 在可用的注入內(nèi)容中搜索用的
提示:
provide
和inject
綁定并不是可響應的克婶,這是刻意為之,然而如果你傳入了一個可監(jiān)聽的對象丹泉,那么氣對象的屬性還是可監(jiān)聽的情萤。
?
# 案例展示
在父組件中provide
提供變量
<template>
<div>
<p>{{ title }}</p>
<son></son>
</div>
</template>
<script>
import Son from "./son"
export default {
name: 'Father',
components: { Son },
// provide選項提供變量
provide: {
message: 'provided by father'
},
data () {
return {
title: '父組件'
}
},
methods: { ... }
}
</script>
在子組件中,我們故意不使用任何父組件的信息
<template>
<div>
<p>{{ title }}</p>
<grand-son></grand-son>
</div>
</template>
<script>
import grandSon from "./grandSon "
export default {
name: "Son",
components: { grandSon },
data () {
return {
title: '子組件'
}
},
};
</script>
在孫組件中摹恨,使用inject
來注入
<template>
<div>
<p>message:{{ message }}</p>
</div>
</template>
<script>
export default {
name: "GrandSon",
inject: [ "message" ],
data () {
return {
title: '孫組件'
}
},
methods: { ... }
};
</script>
結果孫組件頁面顯示:
message: provided by father
?
建議
使用依賴注入時筋岛,強烈建議使用命名空間策略,根據(jù)父組件特性對命名空間名稱做規(guī)范晒哄,可以解決不知道哪里提供的問題睁宰。且依賴注入是單向數(shù)據(jù)流,有統(tǒng)一分發(fā)數(shù)據(jù)的優(yōu)勢寝凌,合理使用能提供很大便利性柒傻。