You need to enable JavaScript to run this app. Vue.js中如何在子组件发起Axios请求时自动触发<b-overlay>遮罩
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js中如何在子组件发起Axios请求时自动触发<b-overlay>遮罩

自动联动b-overlay与子组件Axios请求的实现方案

该方案基于Vue的provide/inject依赖注入能力,无需逐层透传props,不需要引入全局状态管理,完全实现作用域隔离,不会影响页面其他组件的请求逻辑

基础实现(轻量场景优先)

父组件(b-overlay所在组件)

核心逻辑是本地维护请求计数器,通过provide把绑定计数器的请求方法跨层级注入给所有子组件,b-overlay的显示状态直接绑定计数器是否大于0:

<template>
  <b-overlay :show="loadingCount > 0" rounded>
    <child>
      <other-child />
    </child>
  </b-overlay>
</template>

<script setup>
import { ref, provide } from 'vue'
import axios from 'axios'

// 本地请求计数器,处理并发请求:所有请求完成才关闭遮罩
const loadingCount = ref(0)

// 封装与当前遮罩绑定的请求函数,注入给内部所有子组件
provide('scopedAxiosRequest', async (config) => {
  loadingCount.value += 1
  try {
    // 独立Axios实例,避免与全局配置冲突
    const requestInstance = axios.create()
    return await requestInstance(config)
  } finally {
    // 无论请求成功/失败都要重置计数,避免遮罩卡死
    loadingCount.value -= 1
  }
})
</script>

任意层级子组件的使用方式

不管嵌套多少层,子组件直接inject注入的请求方法发请求即可,完全不需要感知遮罩的存在,也不需要手动控制遮罩状态:

<script setup>
import { inject } from 'vue'

// 跨层级接收父组件提供的作用域请求方法
const scopedRequest = inject('scopedAxiosRequest')

const loadTableData = async () => {
  // 直接调用即可,自动触发遮罩显示/隐藏
  const res = await scopedRequest({
    url: '/api/table/list',
    method: 'get'
  })
  // 正常处理返回数据即可
}
</script>

进阶实现(适配已封装全局Axios的项目)

如果项目已经统一封装了全局Axios实例,不需要单独创建独立实例,可以通过唯一作用域标识的方式实现适配:

  • 维护全局的作用域计数器映射表,存储每个遮罩对应的请求计数器
  • 父组件生成唯一的作用域标识,把标识和计数器存入映射表,注入给子组件
  • 子组件发起请求时自动把标识附加到全局Axios的请求配置中
  • 全局Axios拦截器根据请求携带的标识,自动操作对应遮罩的计数器

核心代码示例:

// 全局映射表:存每个遮罩作用域的计数器
const overlayCounterMap = new Map()

// 父组件逻辑
const overlayScopeId = Symbol('overlay-scope') // 唯一标识,不能复用
const loadingCount = ref(0)
overlayCounterMap.set(overlayScopeId, loadingCount)

// 注入给子组件的请求方法
provide('scopedRequest', (config) => {
  return axios({
    ...config,
    overlayScope: overlayScopeId // 把标识附加到请求配置
  })
})

// 全局Axios请求拦截器
axios.interceptors.request.use((config) => {
  if (config.overlayScope) {
    const counter = overlayCounterMap.get(config.overlayScope)
    if (counter) counter.value += 1
  }
  return config
})

// 全局Axios响应拦截器(成功+失败都要重置计数)
axios.interceptors.response.use(
  (res) => {
    if (res.config.overlayScope) {
      const counter = overlayCounterMap.get(res.config.overlayScope)
      if (counter) counter.value -= 1
    }
    return res
  },
  (err) => {
    if (err.config?.overlayScope) {
      const counter = overlayCounterMap.get(err.config.overlayScope)
      if (counter) counter.value -= 1
    }
    return Promise.reject(err)
  }
)

注意事项

  • 计数器必须在请求失败分支/finally中重置,否则会因为请求异常导致遮罩一直显示
  • 作用域标识必须保证唯一,推荐用Symbol()生成,避免不同遮罩的计数器互相干扰
  • 当前b-overlay范围内的所有请求,必须使用注入的作用域请求方法,直接调用全局Axios不会触发联动
  • 如果内部嵌套了其他b-overlay组件,会自动遵循Vue的就近inject规则,不需要额外处理作用域覆盖逻辑

内容的提问来源于stack exchange,提问作者Vinicius Romao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.29 06:24:03