页面在请求接口时,我们通常会加一个loading状态。如果有多个请求,当所有请求都结束才结束loading状态,这个时候你会怎么做?是在页面级上一个个加promise,await,promise.all去处理吗?这种方式确实可以,但是太繁琐了。这里我将教大家在axios的配置文件中去全局封装可以控制多个请求loading的开始与结束,以及接口是否需要loading。
在这里我以vue项目为例,其它框架也是一样的,方法思路都一样,最核心的思想就是在接口封装文件中,通过请求数的增减来控制loading的展示与关闭,通过接口传参控制是否需要loading。
设置全局变量loading
我们首先需要一个全局变量,这个变量可以控制loading的开始与结束,这里我使用vuex
/src/store/modules/common.js
const state = () => ({
isLoading: false
});
const mutations = {
SET_LOADING(state, data) {
state.isLoading = data;
}
};
export default {
namespaced: true,
state,
mutations
};
在App.vue中做一个全局loading动画
在App.vue中引入一个loading组件,这里我是用vant的loading组件做的loading动画效果,通过vuex的loading变量控制显示
/src/components/Loading
<template>
<div v-show="isLoading" class="page-loading">
<van-loading type="circular" color="#fff" vertical>加载中...</van-loading>
</div>
</template>
<script>
import { Loading } from 'vant';
export default {
name: 'PageLoading',
components: { 'van-loading': Loading },
computed: {
isLoading() {
return this.$store.state.common.isLoading;
}
}
};
</script>
<style lang="less">
.page-loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
.van-loading {
position: absolute;
left: 50%;
top: 50%;
padding: 20px 25px 18px 25px;
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.65);
transform: translate(-50%, -65%);
.van-loading__text {
margin-top: 15px;
color: #fff;
}
}
}
</style>
在request.js中通过请求开始与结束状态控制loading的开始与结束
思路:设置一个请求数reqNum,每有一个请求开始则+1,开始loading状态,请求结束则-1,当请求数reqNum为0时,结束loading状态。
/src/request/common.js
import axios from 'axios';
import { store } from "@/store/index";
//每个人的requst封装可能不同,但思路都是一样的
let reqNum = 0;
const startLoading = () => {
if (reqNum === 0) {
//loading开始
store.commit('common/SET_LOADING', true);
}
reqNum++;
};
const endLoading = () => {
if (reqNum <= 0) return;
reqNum--;
if (reqNum === 0) {
//loading结束
store.commit('common/SET_LOADING', false);
}
};
// http request 拦截器
axios.interceptors.request.use(
(config) => {
//请求开始的时候,判断是否有传loading,为true则开始loading
config.loading && startLoading();
return config;
},
(error) => {
return Promise.reject(error);
}
);
// http response 拦截器
axios.interceptors.response.use(
(response) => {
//结束loading
endLoading();
return response;
},
(error) => {
//结束loading
endLoading();
return Promise.reject(error);
}
);
export default axios;
在api文件中设置请求接口,以及传参方式
其它都不重要,注意loading的参数位置,后面调用方法的时候,传loading参数进来判断是否loading,loading默认为true
/src/request/index.js
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
* @param {Object} config [请求时axios的额外配置]
*/
export const post = function (url, params = {}, config = { loading: true }) {
return new Promise((resolve, reject) => {
let future = axios.post(url, params, config);
promiseHandler(future, resolve, reject);
});
};
在接口中传参
statisticalApi: (params) => {
return post('/index/statistical', params,{loading:false});
},
总结:通过全局变量控制loading的显示隐藏,设置全局loading动画,在请求封装文件中通过控制请求数去实现多个请求的loading控制,在api文件中通过传参控制控制是否需要loading,这个弄好之后,以后需要页面loading的接口,只需要传参到api文件的接口接收即可,再也不用在页面级上一个个去写了,其它都没啥~觉得可以点个赞