需求是实现在每次后台请求数据时显示加载动画,请求完成动画消失。
实现方法可以借助之前的axios拦截器,在请求前显示动画,请求结束清除动画。
axios.interceptors.request.use(
(config) => {
// 所有请求之前都要执行的操作
//根据接口传入参数显示加载动画
showFullScreenLoading();
return config;
}, function (err) {
return Promise.reject(err);
}
);
//http response 拦截器
axios.interceptors.response.use((response) => {
// 所有请求完成后都要执行的操作
//暂停加载动画
tryHideFullScreenLoading();
return response;
}, function (err) {
if (err.response) {
switch (err.response.status) {
case 401:
// 返回 401 清除token信息并跳转到登录页面
store.dispatch("logout");
router.replace({
path: 'login',
query: { redirect: router.history.current.fullPath }
});
}
}
return Promise.reject(err);
});
因为我使用的是CDN引入的ElementUI,所以loading动画实现方式为:
则elementUI显示loading加载动画方法为:
function startLoading() {
loading = Vue.prototype.$loading({
lock: true,
text: "加载中...",
background: "rgba(0, 0, 0, 0.8)"
});
}
清除loading加载动画方法为:
function endLoading() {
loading.close();
}
但是需要考虑一个问题,可能同时发起多个请求,而我们显示动画是一次性的,即等当前所有请求完毕后在清除动画。
//声明一个对象用于存储请求个数
let needLoadingRequestCount = 0;
function showFullScreenLoading() {
if (needLoadingRequestCount === 0) {
startLoading();
}
needLoadingRequestCount++;
};
function tryHideFullScreenLoading() {
if (needLoadingRequestCount <= 0) return;
needLoadingRequestCount--;
if (needLoadingRequestCount === 0) {
endLoading();
}
};
目前这个加载动画是全屏 Loading,我的项目是属于后台管理系统,页面头部和菜单栏是不会变化的,所以只需要在主界面里面做动画加载即可。设置的方法是在loading配置参数中添加target来控制。
function startLoading() {
loading = Vue.prototype.$loading({
lock: true,
text: "加载中...",
background: "rgba(0, 0, 0, 0.8)",
target: document.querySelector('.loadingtext')//设置加载动画区域
});
}
至此,还存在一个优化问题,当请求响应很快时,页面会出现闪屏现象,其实是loading加载动画显示后又很快的被清除,就会出现闪屏现象。解决思路是在加载动画中做个延迟如果响应超过某个时间段再显示loading否则就不出现。目前还没想到比较好的解决方法。
|