Vue项目中如何通过请求标识控制Axios拦截器加载器触发
实现带标识控制的Axios加载器拦截器
核心思路
直接在Axios请求配置中添加自定义标识(而非依赖请求头),通过拦截器识别该标识来控制加载器的显示/隐藏,同时用计数机制处理并发请求,避免单个请求结束就误关加载器。
1. 管理加载器状态
用Pinia(或Vuex、全局响应式变量)维护加载状态,这里以Pinia为例:
// stores/loader.js import { defineStore } from 'pinia' export const useLoaderStore = defineStore('loader', { state: () => ({ isLoading: false, loadingCount: 0 // 并发请求计数,防止提前关闭加载器 }), actions: { startLoading() { this.loadingCount++ this.isLoading = true }, stopLoading() { this.loadingCount-- if (this.loadingCount <= 0) { this.isLoading = false this.loadingCount = 0 // 重置避免负数 } } } })
2. 配置Axios拦截器
在Axios实例中添加拦截器,识别请求配置里的showLoader标识:
// utils/axios.js import axios from 'axios' import { useLoaderStore } from '@/stores/loader' const axiosInstance = axios.create({ baseURL: '/api' }) // 请求拦截器 axiosInstance.interceptors.request.use( config => { if (config.showLoader) { const loaderStore = useLoaderStore() loaderStore.startLoading() } return config }, error => { // 请求失败也要关闭对应加载器 if (error.config?.showLoader) { const loaderStore = useLoaderStore() loaderStore.stopLoading() } return Promise.reject(error) } ) // 响应拦截器 axiosInstance.interceptors.response.use( response => { if (response.config.showLoader) { const loaderStore = useLoaderStore() loaderStore.stopLoading() } return response }, error => { if (error.config?.showLoader) { const loaderStore = useLoaderStore() loaderStore.stopLoading() } return Promise.reject(error) } ) export default axiosInstance
3. 发起请求时添加标识
需要显示加载器的请求,在配置中加入showLoader: true,轻量请求则忽略:
// 重量级请求 - 显示加载器 async fetchHeavyData() { try { const res = await axiosInstance.get('/heavy-data', { showLoader: true }) // 处理数据 } catch (err) { // 错误处理 } } // 轻量请求 - 不显示加载器 async fetchLightData() { try { const res = await axiosInstance.get('/light-data') // 处理数据 } catch (err) { // 错误处理 } }
4. 实现加载器组件
写一个全局加载器组件,根据状态自动显示:
<!-- components/Loader.vue --> <template> <div v-if="isLoading" class="loader-overlay"> <div class="loader-spinner"></div> </div> </template> <script setup> import { useLoaderStore } from '@/stores/loader' import { computed } from 'vue' const loaderStore = useLoaderStore() const isLoading = computed(() => loaderStore.isLoading) </script> <style scoped> .loader-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 9999; } .loader-spinner { width: 50px; height: 50px; border: 5px solid #fff; border-top-color: #42b983; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } </style>
最后在App.vue中引入该组件即可全局生效。
关于请求头失败的说明
请求头方案容易踩坑:一是非标准自定义头可能被浏览器/后端框架过滤;二是Axios在某些场景下会自动过滤非HTTP规范头。直接在请求配置中添加自定义字段是更可靠的方案,Axios会完整保留这些配置项。
内容的提问来源于stack exchange,提问作者Oraz Durdyyew
相关产品推荐
相关产品推荐

