前言
在vue
项目中,我们通常会使用Axios
来与后台进行数据交互。而当我们发起请求时,常常需要在页面上显示一个加载框(Loading
),然后等数据返回后自动将其隐藏。要实现这个功能,我们可以在每次请求前手动显示个加载框,等收到数据后又将其隐藏。但如果每个请求要都这么做,就有点麻烦。,但众所周知,程序猿是一种不喜欢麻烦的生物,那么我们要怎么样让这个步骤变得不再那么繁琐呢。
下面通过一个demo
演示如何封装一个带loading
效果的Axios
组件,它能够对请求和响应进行拦截从而实现 loading
的自动显示与隐藏,并且在请求失败时自动弹出消息提示框显示错误信息。
demo
原理说明
- 通过 axios 提供的请求拦截和响应拦截的接口,控制 loading 的显示或者隐藏。同时在请求失败时还会自动弹出消息提示框显示错误信息。
loading
效果采用Element UI
中提供的Loading
组件来实现。而错误消息提示框则用的是Element UI
中的Message
组件来实现。- 内部有个计数器,确保同一时刻如果有多个请求的话,不会同时出现多个 loading,而是只有 1 个。并且在所有请求结束后才会隐藏 loading。
- 使用了
debounce
防抖。因为有时会碰到在一次请求完毕后又立刻又发起一个新的请求的情况。这种情况会造成连续loading
两次,并且中间有一次的闪烁。通过防抖避免闪烁的情况。 - 默认所有请求都会自动有
loading
效果。如果某个请求不需要loading
效果,可以在请求头中showLoading
设置为false
- 默认的
loading
效果是覆盖在body
上。如果某个请求是需要在某个指定元素上显示loading
效果,可以将请求header
中loadingTarget
设置为该元素的选择符。
代码实现
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
,一起交流面经,一起屡败屡战。