解决连续请求,显示loading导致页面闪烁问题
一、背景在实际项目中,一般都会给页面添加 loading,从而提升用户体验。添加 loading 的方式有两种(基于vue+element):1.1 添加到table上这种方式是将 loading主要添加到table组件上,并且在一些需要的地方进行单独处理,如给button添加loading效果。1.2 全局添加这种方式是根据请求全局添加,只有请求就显示loading。一般在全局的ajax封装中处
一、背景
在实际项目中,一般都会给页面添加 loading,从而提升用户体验。
添加 loading 的方式有两种(基于vue+element):
1.1 添加到table上
这种方式是将 loading 主要添加到table组件上,并且在一些需要的地方进行单独处理,如给button添加loading效果。
1.2 全局添加
这种方式是根据请求全局添加,只要请求就显示loading。一般在全局的ajax封装中处理。
这里主要介绍的是全局添加的方式
二、有什么问题
根据请求显示loading(用element 的Loading.service()
即可实现),在一个请求的情况下,就不会有问题。但是如果存在请求一个接一个(连续请求),就会造成页面闪烁(loading显示 => 关闭 => 马上有显示 => 在关闭 …)。效果如下:
三、解决方案
3.1 增加两个变量
在store中增加一个变量 isShowLoading
变量,用来控制是否显示loading(最后在store或者storage中增加,因为会在其他组件中使用)
// 第一步:store 文件夹下的state.js
const state = {
// 控制页面是否正在显示loading
isShowLoading: false
};
// 第二步:store 文件夹下的mutations.js
const SET_SHOWLOADING = 'SET_SHOWLOADING';
const mutations = {
// 设置是否正在加载,显示loading
[SET_SHOWLOADING](state, data) {
state.isShowLoading = data;
}
};
增加一个 loadingCount
变量,用来计算请求的次数
3.2 增加两个方法,来对 loadingCount 进行增减操作
const addLoading = () => {
// 开始请求时,添加数量,并且设置为显示loading
loadingCount++;
store.commit('SET_SHOWLOADING', true);
};
const isCloseLoading = () => {
// 请求完成或者请求失败时,减少正在请求的数量,并且判断是否还有未完成的请求,如果没有了,则设置为隐藏loading
loadingCount--;
if (loadingCount === 0) {
store.commit('SET_SHOWLOADING', false);
}
};
3.3 修改axios拦截器
// 添加请求拦截器
this.$axios.interceptors.request.use(config => {
addLoading()
return config
}, error => {
isCloseLoading()
this.$Message.error('网络异常,请稍后再试')
return Promise.reject(error)
})
// 添加响应拦截器
this.$axios.interceptors.response.use(response => {
isCloseLoading()
return response
}, error => {
isCloseLoading()
this.$Message.error('网络异常,请稍后再试')
return Promise.reject(error)
})
如果没有设置请求拦截,则在请求前调用addLoading
即可;
请求完成,或者失败都需要调用isCloseLoading
,
如下:
const request = (method, url, data, config = {}) => {
// 开启loading,保存正在请求的地址
addLoading();
/*
* to do list
* ...
*/
// 最后返回一个promise
return new Promise((resolve, reject) => {
axios.request(options)
.then((res) => {
const data = res.data;
if (data) {
// TODO 判断code,如果由后台统一返回错误信息,则这里统一提示;如果不是,则调用的地方在判断code
if (data.code === '1') {
isCloseLoading();
resolve(data);
} else {
isCloseLoading();
// TODO 提示message
Message.error(data.msg || data.error);
reject(res);
}
} else {
isCloseLoading();
reject(res);
}
})
.catch((res) => {
removePending(options.url);
isCloseLoading();
// TODO 判断
reject(res);
});
});
};
3.4 在App.vue中处理是否显示loading
<template>
<div id="app">
<!-- 路由跳转 -->
<router-view v-if="isRouterAlive"></router-view>
<div v-if="$store.state.isShowLoading"
class="loading">
<i class="cp-icon"></i>
</div>
</div>
</template>
#app {
height: 100%;
position: relative;
.loading{
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.6);
position: absolute;
top: 0px;
left: 0px;
z-index: 9;
display: flex;
justify-content: center;
align-items: center;
color: $primary;
font-size: 30px;
@keyframes animal {
0%{
transform: rotate(0deg);
-ms-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
-ms-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
}
}
// 自定义旋转动画
i{
color: $primary;
font-size: 40px;
animation: animal 1.4s infinite linear;
transform-origin: center center;
}
}
}
3.5 最终效果
参考文章:多个请求下 loading 的展示与关闭 ==>> 感谢这位大佬提供了一个很好的思路
文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出
对博客文章的参考,若原文章博主介意,请联系删除!请原谅
更多推荐
所有评论(0)