之前我們學(xué)習(xí)過provide和inject的作用,就是在父級組件中provide數(shù)據(jù)或者方法,在他的后代組件中只要直接inject就可以使用這些數(shù)據(jù)或者方法了,
這節(jié)課我們就一起學(xué)習(xí)一下在組合API中使用provide和inject,還是以我們之前寫的titleBar組件為例
1.基本用法
在父組件中使用provide,需要先導(dǎo)入這個方法
import { provide } from 'vue'
provide這個函數(shù)有兩個參數(shù)
provide(name,value)
第一個參數(shù)就是數(shù)據(jù)或者方法的名字,第二個就是它的值,
我們在App.vue中給后代組件provide一個titleColor,表示標(biāo)題欄文字的顏色
setup() {
provide('titleColor', '#333')
},
名字是titleColor,它的值是‘#333’
這樣在父組件中就完成了provide
下面來修改titleBar組件
inject也是一個方法,我們在titleBar中導(dǎo)入它
import { inject } from 'vue'
然后我們根據(jù)父組件中provide的名字獲取到它的值,
最后需要在setup中return這個值,以便在template中使用
setup() {
const titleColor = inject('titleColor') // titleColor就是我們在父組件中provide的名字
return {
titleColor,
}
},
template中使用titleColor
<div class="title" :style="{ color: titleColor }">{{ title }}</div>
我們可以看到父組件中provide的顏色值渲染到了div這個元素上

inject這個方法還有第二個參數(shù),表示如果父級組件沒有provide相應(yīng)的數(shù)據(jù),那它默認(rèn)返回的值
inject(name,defaultValue)
現(xiàn)在我們把父組件中provide的titleColor去掉,
在titleBar組件中,inject時增加一個默認(rèn)值
const titleColor = inject('titleColor', 'red')
這樣我們我頁面標(biāo)題就變成了紅色

2.增加響應(yīng)性
現(xiàn)在我們恢復(fù)上一步的代碼,還是由App.vue來provide titleColor這個數(shù)據(jù),
我們現(xiàn)在來provide一個有響應(yīng)性的值,只需要用ref或者reactive來定義數(shù)據(jù)就行了
在App.vue中修改
const titleColor = ref('#333')
provide('titleColor', titleColor)
這樣titleColor這個數(shù)據(jù)就有響應(yīng)性了,
我們在onMounted中,改變它的值
setup() {
const titleColor = ref('#333')
provide('titleColor', titleColor)
onMounted(() => {
titleColor.value = 'green' // 改變了數(shù)據(jù)titleColor的值
})
},
在titleBar中的代碼不用修改,還是像以前一樣inject titleColor這個數(shù)據(jù)
setup() {
const titleColor = inject('titleColor', 'red')
return {
titleColor,
}
},
它接收到green這個值,覆蓋了它的默認(rèn)值red,所以最后頁面標(biāo)題的顏色是綠色的

3.子組件如何改變inject的值
如果我們想在子組件中改變父組件provide的titleColor這個值,不可以在子組件中直接修改,因為這樣會導(dǎo)致代碼邏輯混亂,降低代碼的可維護性,我們的原則是子級組件不要去改變父級組件的
這時正確的方式是在父組件中定義一個改變titleColor的方法,然后把這個方法provide給子組件
在App.vue中增加changeTitleColor這個方法
setup() {
const titleColor = ref('#333')
const changeTitleColor = () => { // 增加改變titleColor的方法
titleColor.value = 'blue'
}
provide('titleColor', titleColor)
provide('changeTitleColor', changeTitleColor) // 把這個方法provide給子組件
},
在子組件中調(diào)用changeTitleColor方法
setup() {
const titleColor = inject('titleColor', 'red')
const changeTitleColor = inject('changeTitleColor') // inject這個方法
onMounted(() => {
changeTitleColor() //在組件掛載以后調(diào)用,就可以改變titleColor的值了
})
return {
titleColor,
}
},
現(xiàn)在我們的頁面標(biāo)題變成了藍(lán)色

更進(jìn)一步,為了防止子組件中修改provide的數(shù)據(jù),可以在provide時使用readonly
在App.vue中導(dǎo)入readonly這個方法
import { provide, ref, readonly } from 'vue'
在provide數(shù)據(jù)時,增加readonly
setup() {
const titleColor = ref('#333')
const changeTitleColor = () => {
titleColor.value = 'blue'
}
provide('titleColor', readonly(titleColor)) // 新增
provide('changeTitleColor', changeTitleColor)
},
這樣子組件中就不能更改titleColor的值了,我們可以更改一下試試,看看會怎么樣
setup() {
const titleColor = inject('titleColor', 'red')
titleColor.value = 'blue' // 更改titleColor,會有警告,而且更改也不會生效
return {
titleColor,
}
},
這樣寫時,控制臺會輸出一個警告

同時更改也不會有效果
這節(jié)課內(nèi)容就到這里,基本都是對provide/inject的一個復(fù)習(xí),只是寫法不一樣了而已。