chaihongjun.me

Vue3跨组件通信控制加载状态使用provide和inject的案例分析

核心问题:跨组件通信控制加载状态。父组件需要等待所有子组件的API数据请求完成后,才隐藏 loading。但子组件的数据请求在各自内部完成,父组件无法直接感知,通过provide和inject方法可以让父组件得到反馈。

案例:

<!-- 父组件 -->
<template>
    <van-loading v-if="loading" class="loading" />
    <template v-else>
        <div class="container">
          <Banner></Banner> <!-- banner组件需要通过API获取数据  -->
        </div>
    </template>
</template>

父组件需要等待子组件banner加载之后,才隐藏loading。这里子组件banner内部实际是有一个API的请求方法:

// 子组件
<script setup>
import { inject, onMounted } from 'vue';


onMounted(async () => {
  try {
    const res = await fetchBanner(); //API请求
    if (res.code === 0) {
      banners.value = res.data;
    }
  } catch (error) {
    console.error("Banner加载失败:", error);
  } finally {

  }
});
</script>

构想是父组件页面加载的时候先显示loading动画,然后等待子组件API数据请求完毕了,再隐藏loading动画,然后正确的显示父组件页面。那么就需要子组件在完成数据请求之后“通知”父组件。这里可以使用provide/inject达到这个目的。当然除了父子组件关系,其他层级关系的组件也可以是使用provide/inject。

首先,需要在父组件内provide提供一个资源,这里是一个函数将给到子组件进行调用,这个函数作用是用来记录子组件加载完成这个事情(计数)。

//父组件
<script setup>
import { ref, provide } from 'vue';

const loadedCount = ref(0);          // 已完成加载的组件计数
const expectedLoadCount = 2;         // 预期需要加载的子组件总数


// 注册组件加载完成的函数
// 当某子组件加载完成,这个函数将被执行一次
const registerComponentLoad = () => {
  loadedCount.value++; //计数器
  console.log(`组件加载完成: ${loadedCount.value}/${expectedLoadCount}`);
  
  // 当所有子组件加载完成时关闭loading
  if (loadedCount.value >= expectedLoadCount) {
    loading.value = false;
  }
};

// 将函数提供给所有后代组件
provide('registerComponentLoad', registerComponentLoad);
</script>

子组件需要在合适的地方调用父组件给的资源,这里是计数函数:

//子组件
<script setup>
import { ref,inject, onMounted } from 'vue';

const banners = ref([])

// 从父组件注入注册函数(默认空函数防止报错)
const registerComponentLoad = inject('registerComponentLoad', () => {});

onMounted(async () => {
  try {
    const res = await fetchBanner(); //API请求
    if (res.code === 0) {
      banners.value = res.data;
    }
  } catch (error) {
    console.error("Banner加载失败:", error);
  } finally {
    // 无论成功/失败都通知父组件"我已完成"
    registerComponentLoad();
  }
});
</script>

子组件在完成API请求,并将结果赋值给对应的响应式变量之后,去执行provide的函数。这样预期的效果就实现了。

Vue3跨组件通信控制加载状态使用provide和inject的案例分析

最后总结一下,当组件之间通信,某个组件需要等待另外一个组件(或者多个组件)"反馈"一些信息之后再做动作,可以使用provide/inject方法完成。provide提供的资源可以是一个响应式数据,也可以是一个回调函数,资源的形式主要看其他组件实际需要提供者具体做什么。

知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:柴宏俊»