一、背景
日常开发中,经常需要使用v-loading指令展示加载动画,表示数据正在加载中。
通常在ajax请求前后对v-loading绑定值进行改变。如:
const queryData = ()=>{
isLoading = true;
ajax(url,data).then().finally(()=>{
isLoading = false;
})
}
当页面中有个请求时,需要在相应请求都完成后再将v-loading设置成false。
在Vue3中,推荐使用composition api对模块进行封装,据此,个人设计了useLoading
二、useLoading 代码
// useLoading.ts
import { ref, computed } from "vue";
export const useLoading = () => {
// 使用number类型的loadingIndex,而不是boolean类型,用于有多个请求的场景
const loadingIndex = ref(0);
// 计算属性,根据loadingIndex的值判断为true/false
const isLoading = computed(() => {
return loadingIndex.value <= 0 ? false : true;
});
// 进入loading,loadingIndex的值加1
const enterLoading = () => {
loadingIndex.value += 1;
};
// 退出loading,loadingIndex的值减1
const quitLoading = () => {
if (loadingIndex.value > 0) {
loadingIndex.value -= 1;
} else {
console.warn("no need quit loading");
}
};
// loadingWrapper方法,自动完成进入/退出loading的设置
const loadingWrapper = <T>(promise: Promise<T>) => {
return new Promise<void>((resolve, reject) => {
// 进入loading
enterLoading();
promise.finally(() => {
// 退出loading
quitLoading();
resolve();
});
});
};
return {
isLoading,
enterLoading,
quitLoading,
loadingWrapper,
};
};
三、使用示例
// 在业务组件中
<template>
<div v-loading="isLoading"></div>
</template>
<script lang='ts' setup>
import { useLoading } from '@/hooks'
const { isLoading, loadingWrapper } = useLoading()
// 请求数据的方法
const queryDataList = () => {
// 使用loadingWrapper,自动完成进入/退出loading的设置
loadingWrapper(DataApi.queryData({}).then(res => {
let data = res.data.data.list
data = clearButtonType(data)
clearEmptyChildren(data)
allMenuList.value = data
}))
}
</script>