描述: 添加全局loading目的是减少页面写v-loading指令, 这样我们只需要配置参数就可以控制每个请求是否需要loading,并且可以配置正在loading的元素, 这里通过请求时配置header参数进行控制, 网上都有教程了,这里也是记录一下,方便自己以后查看.
实现代码:
我loading方法放在utils文件夹下
import { debounce } from "./funDebounce";
//import { Loading } from 'element-ui' // 装包方式这样引入,我这里通过cdn引入,通过window.ELEMENT调用
// loading对象
let loading;
// 当前正在请求的数量
let needLoadingRequestCount = 0;
// 显示loading
export function showLoading(target) {
// 后面这个判断很重要,因为关闭时加了抖动,此时loading对象可能还存在,
// 但needLoadingRequestCount已经变成0.避免这种情况下会重新创建个loading
console.log(needLoadingRequestCount, loading);
if (needLoadingRequestCount === 0 && !loading) {
loading = window.ELEMENT.Loading.service({ // 通过cdn引入的element-ui
lock: true,
text: "加载中...",
background: "rgba(255, 255, 255, 0.7)",
target: target || "#micro-apps-container"
});
}
needLoadingRequestCount++;
}
// 隐藏loading
export function hideLoading() {
needLoadingRequestCount--;
needLoadingRequestCount = Math.max(needLoadingRequestCount, 0); // 做个保护
if (needLoadingRequestCount === 0) {
// 关闭loading
toHideLoading();
}
}
// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次。防止连续请求时, loading闪烁的问题。
let toHideLoading = debounce(() => {
loading.close();
loading = null;
}, 300);
上面用到的 防抖节流函数:
/**
* @desc 函数防抖
* @param func 目标函数
* @param wait 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
* 立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果
非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
*/
export function debounce(func, wait, immediate) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) clearTimeout(timer);
if (immediate) {
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) func.apply(context, args);
} else {
timer = setTimeout(() => {
func.apply(context, args);
}, wait);
}
};
}
// 定时器版-节流
export function throttle(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args);
}, wait);
}
};
}
引入我们配置全局拦截文件:
这边只是介绍了loading引入,其他拦截配置大家按照自己项目配置.
import { showLoading, hideLoading } from "@/utils/requestLoading";
import axios from 'axios'
let configChace = null; // 存放请求参数,在进入错误时候也关掉loading
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 判断当前请求是否设置了不显示Loading,默认显示
if (config.headers.showLoading) {
showLoading(config.headers.loadingTarget); // 如果设置了targer,使用设置的target,比如el-table
configChace = config;
}
return config;
}, function (error) {
// 对请求错误做些什么
// 关闭loading
if (configChace.headers.showLoading) {
hideLoading();
configChace = null;
}
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
// 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
if (response.config.headers.showLoading) {
hideLoading();
}
return response;
}, function (error) {
// 对响应错误做点什么
// 关闭loading
if (configChace.headers.showLoading) {
hideLoading();
configChace = null;
}
return Promise.reject(error);
});
使用:
通过配置header参数控制是否要Loding:
import { axios, post } from "./settings"; // 封装好的请求方法
export const stuSubjectApi = params => {
return axios({
url: "xxx",
method: "get",
params,
headers: { showLoading: true, loadingTarget: 'xxx' }
});
};
然后在项目调用接口就可以了.