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

相关推荐
桂月二二20 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
沈梦研1 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
轻口味2 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架