provide/inject
provide
(提供)和 inject
(注入)也可以在组合式 API 的 setup
方法中使用,以实现跨越层级的组件通信。
provide
方法接收两个参数,一个是提供数据的 key
;另一个是值 value
,也可以是对象、方法等,如示例代码 4-7-1 所示。
示例代码 4-7-1 provide 方法
<div id="app">
<component-b />
</div>
Vue.createApp({
components: {
'component-b': componentB
},
setup() {
Vue.provide('location', 'North Pole')
Vue.provide('geolocation', {
longitude: 90,
latitude: 135
})
}
}).mount("#app")
inject
方法接收两个参数,一个是需要注入的数据的 key
,另一个是默认值(可选),如示例代码 4-7-2 所示。
示例代码 4-7-2 inject 方法
const componentB = {
template:'<div>{{userLocation}}</div>',
setup() {
const userLocation = Vue.inject('location', 'The Universe')
const userGeolocation = Vue.inject('geolocation')
console.log(userGeolocation)
return {
userLocation,
userGeolocation
}
},
}
和之前的配置式 API 不同的是,我们可以在 provide
值时使用 ref
或 reactive
方法,来增加 provide
值和 inject
值之间的响应性。这样,当 provide
的数据发生变化时,inject
也能实时接收到,如示例代码 4-7-3 所示。
示例代码 4-7-3 响应式 provide 数据
<div id="app">
<component-b></component-b>
</div>
const componentB = {
template:'<div>{{userLocation}}</div>',
setup() {
const userLocation = Vue.inject('location', 'The Universe')
const userGeolocation = Vue.inject('geolocation')
console.log(userGeolocation)
return {
userLocation,
userGeolocation
}
},
}
Vue.createApp({
components: {
'component-b': componentB
},
setup() {
const location = Vue.ref('North Pole')
const geolocation = Vue.reactive({
longitude: 90,
latitude: 135
})
Vue.provide('location', location)
Vue.provide('geolocation', geolocation)
setTimeout(() => {
location.value = 'China'
},1000)
},
}).mount("#app")
通常情况下,只允许在 provide
的组件内去修改响应式的 provide
数据,但是如果需要在被 inject
的组件内去修改 provide
的值,则需要 provide
一个回调方法,然后在被 inject
的组件内调用,如示例代码4-7-4所示。
示例代码 4-7-4 响应式 provide 数据
<div id="app">
<component-b></component-b>
</div>
const componentB = {
template:'<div>{{userLocation}}</div>',
setup() {
const userLocation = Vue.inject('location', 'The Universe')
const updateLocation = Vue.inject('updateLocation')
setTimeout(() => {
updateLocation('China')
},1000)
return {
userLocation,
}
},
}
Vue.createApp({
components: {
'component-b': componentB
},
setup() {
const location = Vue.ref('North Pole')
const updateLocation = (v) => {
location.value = v
}
Vue.provide('location', location)
Vue.provide('updateLocation', updateLocation)
},
}).mount("#app")
最后,如果要确保通过 provide
传递的数据不会被 inject
的组件更改,则可以使用 readonly
方法,代码如下:
const location = Vue.ref('North Pole')
Vue.provide('location', Vue.readonly(location))