Vue + Axios实现全局Loading自动显示关闭效果

前言

vue项目中,我们通常会使用Axios来与后台进行数据交互。而当我们发起请求时,常常需要在页面上显示一个加载框(Loading),然后等数据返回后自动将其隐藏。要实现这个功能,我们可以在每次请求前手动显示个加载框,等收到数据后又将其隐藏。但如果每个请求要都这么做,就有点麻烦。,但众所周知,程序猿是一种不喜欢麻烦的生物,那么我们要怎么样让这个步骤变得不再那么繁琐呢。

下面通过一个demo演示如何封装一个带loading效果的Axios组件,它能够对请求和响应进行拦截从而实现 loading的自动显示与隐藏,并且在请求失败时自动弹出消息提示框显示错误信息。

demo

原理说明

  1. 通过 axios 提供的请求拦截和响应拦截的接口,控制 loading 的显示或者隐藏。同时在请求失败时还会自动弹出消息提示框显示错误信息。
  2. loading效果采用 Element UI 中提供的 Loading组件来实现。而错误消息提示框则用的是 Element UI 中的 Message 组件来实现。
  3. 内部有个计数器,确保同一时刻如果有多个请求的话,不会同时出现多个 loading,而是只有 1 个。并且在所有请求结束后才会隐藏 loading。
  4. 使用了debounce防抖。因为有时会碰到在一次请求完毕后又立刻又发起一个新的请求的情况。这种情况会造成连续loading两次,并且中间有一次的闪烁。通过防抖避免闪烁的情况。
  5. 默认所有请求都会自动有loading效果。如果某个请求不需要loading效果,可以在请求头中 showLoading设置为false
  6. 默认的 loading 效果是覆盖在body上。如果某个请求是需要在某个指定元素上显示 loading 效果,可以将请求 headerloadingTarget 设置为该元素的选择符。

代码实现

http.js

js 复制代码
import axios from 'axios';
import { Message,Loading } from 'element-ui';
import _ from 'lodash';
  
const http = axios.create({
    baseURL:process.env.BASE_URL, //设置请求的base url
    timeout:40000 //超时时长
});
  
//loading
let loading;
  
//当前正在请求的数量
let LoadingRequestCount = 0;
  
//显示loading
function showLoading(target) {
  if (LoadingRequestCount === 0 && !loading) {
    loading = Loading.service({
      lock: true,
      text: "加载中",
      background: 'rgba(255, 255, 255)',
      target: target || "body"
    });
  }
  LoadingRequestCount++;
}
  
//隐藏loading
function hideLoading() {
  LoadingRequestCount--;
  LoadingRequestCount = Math.max(LoadingRequestCount, 0); //防止小于0的情况发生
  if (LoadingRequestCount === 0) {
    //关闭loading
    toHideLoading();
  }
}
  
//防抖
var toHideLoading = _.debounce(()=>{
      loading.close();
      loading = null;
    }, 100);
  
//添加请求拦截器
http.interceptors.request.use(config => {
  //判断当前请求是否设置了不显示Loading
  if(config.headers.showLoading !== false){
    showLoading(config.headers.loadingTarget);
  }
  return config;
}, err => {
  //判断当前请求是否设置了不显示Loading
  if(config.headers.showLoading !== false){
    hideLoading();
  }
  Message.error('请求失败!');
  //抛出错误
  return Promise.resolve(err);
});
  
//响应拦截器
http.interceptors.response.use(
    response => {
      //判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
      if(response.config.headers.showLoading !== false){
        hideLoading();
      }
      
      return response;
    },
    error => {
      //判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
      if(error.config.headers.showLoading !== false){
        hideLoading();
      }
      
      if(error.response && error.response.data && error.response.data.message) {
        var jsonObj = JSON.parse(error.response.data.message);
        Message.error(jsonObj.message);
      }else{
        Message.error(error.message);
      }
      return Promise.reject(error);
    }
);
  
export default http;

结语

如果这篇文章对你有帮助的话,欢迎点个赞收藏一下,你的点赞是对作者最好的激励,最后如果您也和我一样准备春招,,欢迎加我微信lx3122178991,一起交流面经,一起屡败屡战。

相关推荐
晴殇i几秒前
抛弃 JavaScript 立即执行函数,这个方案更简洁更优雅
前端·javascript
码是生活1 分钟前
鸿蒙开发排坑:解决 resourceManager.getRawFileContent() 获取文件内容为空问题
前端·harmonyos
zoahxmy09292 分钟前
Vue3 视频播放与截图功能实现
javascript·vue.js
婷婷婷婷4 分钟前
v-copyText 自定义指令 —— 复制文本内容
前端
waylon111136 分钟前
【HOC】高阶组件在Vue老项目中的实战应用 - 模块任意排序
前端·vue.js·面试
阳阳羊7 分钟前
Mpx 动画
前端
编程社区管理员7 分钟前
「2025最新版React+Ant Design+Router+TailwindCss全栈攻略:从零到实战,打造高颜值企业级应用
前端·react.js·前端框架
DJA_CR8 分钟前
解决在 TSX 中使用 `RouterView` + `KeepAlive` 不生效问题
前端·vue.js
前端爆冲18 分钟前
项目中无用export的检测方案
前端
小旋风0123424 分钟前
封装可拖动弹窗(vue jquery引入到html的版本)
vue.js·html·jquery