import { customRef } from 'vue';
export const loading = customRef((track, trigger) => {
let loadingCount = 0;
return {
get() {
track();
return loadingCount > 0;
},
set(value) {
loadingCount += value ? 1 : -1;
loadingCount = Math.max(loadingCount, 0);
trigger();
}
}
})
export async function request(url: string, params: Record<string, string>) {
const query = new URLSearchParams(params).toString();
// 请求之前开启loading
loading.value = true;
return fetch(`${url}?${query}`).then((res) => res.json()).finally(() => {
// 请求结束, 关闭 loading
loading.value = false;
})
}
原理:
- 使用 Vue 的 customRef 创建了一个自定义的响应式引用
- 内部维护了一个 loadingCount 计数器
- get 方法返回 loadingCount > 0 的布尔值
- set 方法根据传入的值增减计数器
- 使用 track 和 trigger 实现响应式更新
特点:
- 支持多个请求同时进行时的 loading 状态管理
- 只有当所有请求都完成时,loading 才会变为 false
功能:
- 封装了一个异步请求函数
- 自动处理 URL 参数拼接
- 自动管理 loading 状态
使用场景:
- 在 Vue 应用中管理多个异步请求的加载状态
- 适用于需要显示全局加载状态的场景
- 可以避免多个请求同时进行时 loading 状态闪烁的问题
注意事项:
- loading 状态是基于计数器的,所以可以同时处理多个请求
- finally 确保无论请求成功还是失败,loading 状态都会被正确更新
- loadingCount 使用 Math.max 确保不会出现负数
- 这个实现特别适合需要统一管理加载状态的应用