💡Vue3 + Element Plus 中如何优雅实现全局 Loading 控制(含接口白名单机制)
在中大型 Vue 3 项目中,页面中常常存在多个异步请求。为了提升用户体验,我们希望在发起接口请求时自动展示 Loading
,请求结束后自动关闭,同时避免对“轻量级接口”重复展示 loading 遮罩。
本文将介绍一种结合 Axios + Element Plus 的“全局 loading 控制 + 白名单机制”方案,适合大部分 B 端项目落地使用。
🎯目标
- 请求发起时自动展示
ElLoading
- 响应返回后自动关闭 loading
- 某些接口(如查询未读数、获取下拉选项)不展示 loading
- 多个接口并发时避免闪烁和重复 loading
🧱项目依赖
- Vue 3.x
- Element Plus
- Axios
- Pinia(可选)
🧩实现思路
- 使用 Axios 拦截器统一处理请求/响应
- 引入接口白名单机制
- 使用全局变量管理 loading 实例,避免重复弹窗
✅核心实现代码
import axios from 'axios';
import { ElLoading } from 'element-plus';
let loadingInstance: any = undefined;
// 白名单接口:这些接口不触发 Loading 遮罩
const unloadingUrlList = [
'message/unreadNum',
'form/dynamicFormList',
'org/tree',
// 可继续添加接口关键词
];
// 判断接口是否命中白名单
function isUnloadingUrl(url: string = '') {
return unloadingUrlList.some((murl) => url.includes(murl));
}
// 创建 Axios 实例
const service = axios.create({
baseURL: '/api',
timeout: 60000,
});
// 请求拦截器
service.interceptors.request.use((config) => {
const url = config.url || '';
if (!loadingInstance && !isUnloadingUrl(url)) {
loadingInstance = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.5)',
});
}
return config;
}, (error) => {
if (loadingInstance) {
loadingInstance.close();
loadingInstance = undefined;
}
return Promise.reject(error);
});
// 响应拦截器
service.interceptors.response.use((response) => {
const url = response.config.url || '';
if (loadingInstance && !isUnloadingUrl(url)) {
loadingInstance.close();
loadingInstance = undefined;
}
return response.data;
}, (error) => {
if (loadingInstance) {
loadingInstance.close();
loadingInstance = undefined;
}
return Promise.reject(error);
});
export default service;
📌白名单机制的优势
- 👁 避免频繁“加载中”闪烁
- 🧠 无需每次手动处理 loading 展示逻辑
- 🔧 可灵活扩展为配置项、正则匹配、环境区分等