Vue中如何向provide/inject异步写入响应式数据?
问题根因
provide 会在父组件初始化阶段同步执行,此时异步fetch请求还未返回,this.sliderData 仍为初始空值;且默认情况下provide传递的普通值不具备响应性,后续父组件数据更新后inject端无法感知变化,因此最终拿到的始终是空值。
解决方案
根据你使用的Vue版本,可选择对应实现方式:
1. Vue 3 选项式API实现
用computed包裹要传递的数据,即可维持响应性,异步更新后子组件自动同步:
// 父组件 import { computed } from 'vue' export default { data() { return { sliderData: [], modelData: [] } }, async fetch() { const res = await requestApi(this, '/database'); this.sliderData = res.homeSlider; this.modelData = res.model; }, provide() { return { // 用computed包裹后传递的是响应式引用 sliderData: computed(() => this.sliderData), modelData: computed(() => this.modelData) } } }
子组件直接注入使用即可,模板中可直接读取值:
// 任意层级子组件 export default { inject: ['sliderData', 'modelData'] }
<!-- 子组件模板 --> <div>{{ sliderData.value }}</div>
2. Vue 3 组合式API实现
直接传递ref/reactive类型的响应式引用即可:
// 父组件setup import { ref, provide } from 'vue' export default { setup() { const sliderData = ref([]) const modelData = ref([]) const fetchData = async () => { const res = await requestApi('/database') sliderData.value = res.homeSlider modelData.value = res.model } fetchData() // 直接传递响应式引用 provide('sliderData', sliderData) provide('modelData', modelData) } }
3. Vue 2 适配实现
Vue2中可将需要传递的数据统一放到一个响应式对象中,直接传递该对象的引用即可:
// 父组件 export default { data() { return { // 所有要共享的异步数据统一挂载到该响应式对象下 sharedAsyncData: { sliderData: [], modelData: [] } } }, async fetch() { const res = await requestApi(this, '/database'); this.sharedAsyncData.sliderData = res.homeSlider; this.sharedAsyncData.modelData = res.model; }, provide() { // 传递响应式对象的引用 return { sharedAsyncData: this.sharedAsyncData } } }
子组件注入后直接读取对应属性即可:
// 子组件 export default { inject: ['sharedAsyncData'], computed: { sliderData() { return this.sharedAsyncData.sliderData } } }
可选优化:增加加载状态兜底
可同时传递加载状态,避免数据未返回时页面出现异常报错:
// 父组件provide新增 provide('dataLoading', computed(() => this.loading)) // 子组件根据状态渲染 <div v-if="dataLoading">加载中...</div> <div v-else>实际内容</div>
内容的提问来源于stack exchange,提问作者macdakilla
相关产品推荐
相关产品推荐

