官網(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ù)流向和合理的組件層級關系便于調試和維護,然而這對選項支持任意層級都能訪問,導致數(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為:- 在可用的注入內容中搜索用的
key,或 - 一個對象,其
from屬性是在可用的注入內容中搜索用的key,default屬性是降級情況下使用的value
- 在可用的注入內容中搜索用的
提示:
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)勢,合理使用能提供很大便利性。