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

相关推荐
牛十二8 分钟前
mac-intel操作系统go-stock项目(股票分析工具)安装与配置指南
开发语言·前端·javascript
whysqwhw16 分钟前
Kuikly 扩展原生 API 的完整流程
前端
whysqwhw17 分钟前
Hippy 跨平台框架扩展原生自定义组件
前端
OEC小胖胖20 分钟前
页面间的导航:`<Link>` 组件和 `useRouter`
前端·前端框架·web·next.js
faimi1 小时前
🚀程序员必收藏!最全Git命令手册:解决90%团队协作难题
前端·gitlab
coooliang2 小时前
【鸿蒙 NEXT】V1迁移V2状态管理
java·前端·harmonyos
程序员码歌2 小时前
零代码AI编程实战-热搜从0到1技术方案
前端·ai编程·cursor
kk不中嘞2 小时前
浅谈前端框架
前端·vue.js·react.js·前端框架
服务端技术栈2 小时前
历时 1 个多月,我的第一个微信小程序「图片转 Excel」终于上线了!
前端·后端·微信小程序
一个很老的小萌新2 小时前
json 解析 [{“id“:1,“name“:“apple“},{“id“:2,“name“:“banana“}]
java·前端·json