Vue3 + Element Plus 中如何优雅实现全局 Loading 控制(含接口白名单机制

33 阅读1分钟

💡Vue3 + Element Plus 中如何优雅实现全局 Loading 控制(含接口白名单机制)

在中大型 Vue 3 项目中,页面中常常存在多个异步请求。为了提升用户体验,我们希望在发起接口请求时自动展示 Loading,请求结束后自动关闭,同时避免对“轻量级接口”重复展示 loading 遮罩。

本文将介绍一种结合 Axios + Element Plus 的“全局 loading 控制 + 白名单机制”方案,适合大部分 B 端项目落地使用。


🎯目标

  • 请求发起时自动展示 ElLoading
  • 响应返回后自动关闭 loading
  • 某些接口(如查询未读数、获取下拉选项)不展示 loading
  • 多个接口并发时避免闪烁和重复 loading

🧱项目依赖

  • Vue 3.x
  • Element Plus
  • Axios
  • Pinia(可选)

🧩实现思路

  1. 使用 Axios 拦截器统一处理请求/响应
  2. 引入接口白名单机制
  3. 使用全局变量管理 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 展示逻辑
  • 🔧 可灵活扩展为配置项、正则匹配、环境区分等