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

相关推荐
科技探秘人4 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人4 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR10 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香12 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969315 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai20 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_91529 分钟前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫6 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试