provide/inject可以穿过多层级组件进行传值,provide/inject与composition api一起使用,两者都只能在setup()当前活动实例期间调用。
Provide
在setup()中使用provide时,需要在vue中导出provide,我们可以根据需求定义每个provide的属性,provide函数允许定义该属性的名称和属性的值。
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
provide('location', 'North Pole')
provide('geolocation', {
longitude: 90,
latitude: 135
})
}
}
</script>
Inject
在setup()中使用inject时,需要在vue中导出inject,inject函数有两个参数,一个是要注入的属性的名称,一个是默认值,为可选项。
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
Reactivity
为了使provide和inject之间有响应式,我们可以在提供者使用ref或者reactive这两个composition api实现关联。
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
}
}
</script>
当提供者的任意属性发生变化,接收的组件也会自动更新。在使用provide和inject时,建议尽可能在提供方对响应式属性进行更改。但是,有时我们需要更新注入数据的组件内部的数据。在这种情况下,我们建议提供一种负责改变响应式属性的方法。官网例子:
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', location)
provide('geolocation', geolocation)
provide('updateLocation', updateLocation)
}
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
const updateUserLocation = inject('updateLocation')
return {
userLocation,
userGeolocation,
updateUserLocation
}
}
}
</script>