目录
一、思路:
1、主要逻辑
利用vue中的仓库(vue2可用vuex,vue3可用pinia,本例为vue2),创建一个全局可访问参数isLoading,当请求时,isLoading为true,结束时为false。
2、优化
思路来自于引用计数圾回收机制,可增加新全局参数loadingResCount,每次请求开始时,通过拦截器使loadingResCount数加一,结束时loadingResCount数减一,当loadingResCount为0时,isLoading为false。
3、所需知识
vuex、request拦截器,elementui中loading组件
二、具体实施:
1、store
新建loading.js文件(和其他store放在同一目录下),此文件用来存放loading显示隐藏逻辑
vuex使用请参考官网:开始 | Vuex
const state = {
isLoading: false,
loadingResCount: 0,
};
const mutations = {
startLoading(state) {
if (state.loadingResCount === 0) {
state.isLoading = true;
}
state.loadingResCount++;
},
endLoading(state) {
if (state.loadingResCount <= 0) return;
state.loadingResCount--;
if (state.loadingResCount === 0) {
state.isLoading = false;
}
},
};
const actions = {
startLoading(context) {
context.commit("startLoading");
},
endLoading({ commit }) {
commit("endLoading");
},
};
export default {
state,
mutations,
actions,
};
2、请求拦截器
每次请求调用startLoading方法,当请求发生错误时,调用endLoading方法
此处做了个小优化,当下拉框是通过api请求数据时,不触发全局loading,具体实现是判断headers中的loading参数,如果为false,则不进入全局loading计数器
// request拦截器
service.interceptors.request.use(
(config) => {
// 下拉联动筛选不需要loading
if (config.headers.loading !== false) {
store.dispatch("startLoading");
}
return config;
},
(error) => {
dispatch.dispatch("endLoading");
console.log(error);
Promise.reject(error);
}
);
export function selectApi(data) {
return request({
url: 'api',
method: 'get',
params: data,
headers: {
loading: false,
},
});
}
3、响应拦截器
每次响应调用endLoading,使loadingResCount减一,这里注意使用了try,catch代码块,最后都会走finally,所以只在finally中调用endLoading
// 响应拦截器
service.interceptors.response.use(
(res) => {
try {
return res.data;
} catch {
console.log("响应拦截器异常");
} finally {
store.dispatch("endLoading");
}
},
(error) => {
store.dispatch("endLoading");
return Promise.reject(error);
}
);
4、使用loading组件
最后在全局loading组件中,将变量绑定到v-loading
<div class="main-container" v-loading="$store.state.loading.isLoading" element-loading-text="加载中...">
</div>
好啦,完结撒花,如果对你有帮助请不要吝啬点赞和收藏哦~