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,一起交流面经,一起屡败屡战。

相关推荐
jingling5554 小时前
vue | 在 Vue 3 项目中集成高德地图(AMap)
前端·javascript·vue.js
油丶酸萝卜别吃4 小时前
Vue3 中如何在 setup 语法糖下,通过 Layer 弹窗组件弹出自定义 Vue 组件?
前端·vue.js·arcgis
J***Q29211 小时前
Vue数据可视化
前端·vue.js·信息可视化
JIngJaneIL11 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
ttod_qzstudio12 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
_大龄12 小时前
前端解析excel
前端·excel
1***s63212 小时前
Vue图像处理开发
javascript·vue.js·ecmascript
一 乐13 小时前
应急知识学习|基于springboot+vue的应急知识学习系统(源码+数据库+文档)
数据库·vue.js·spring boot
一叶茶13 小时前
移动端平板打开的三种模式。
前端·javascript
前端大卫13 小时前
一文搞懂 Webpack 分包:async、initial 与 all 的区别【附源码】
前端