mirror of
https://gitee.com/xiaonuobase/snowy.git
synced 2026-10-06 06:52:58 +08:00
【底座】新增loading和request hook
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
// useLoading.js
|
||||
import { ref } from 'vue';
|
||||
|
||||
export function useLoading(name, initialValue = false) {
|
||||
// 参数校验:name 必须是非空字符串
|
||||
if (typeof name !== 'string' || !name.trim()) {
|
||||
throw new Error('useLoading: first argument "name" must be a non-empty string');
|
||||
}
|
||||
|
||||
const loading = ref(initialValue);
|
||||
const capName = name.charAt(0).toUpperCase() + name.slice(1); // 首字母大写
|
||||
|
||||
const start = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
const stop = () => {
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
return {
|
||||
[`${name}Loading`]: loading, // 动态命名:userLoading
|
||||
[`start${capName}Loading`]: start, // 动态命名:startUserLoading
|
||||
[`stop${capName}Loading`]: stop // 动态命名:stopUserLoading
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
使用示例:
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- 直接使用动态生成的变量名 -->
|
||||
<div v-if="userLoading" class="loading-indicator">用户数据加载中...</div>
|
||||
|
||||
<button
|
||||
@click="handleFetch"
|
||||
:disabled="userLoading"
|
||||
>
|
||||
{{ userLoading ? '加载中...' : '获取用户数据' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useLoading } from './useLoading';
|
||||
import { fetchUserDataAPI } from '@/api';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
// 严格按您的要求调用:
|
||||
// 第一个参数 = name ('user')
|
||||
// 第二个参数 = initialValue (false)
|
||||
const {
|
||||
userLoading, // 响应式 loading 状态
|
||||
startUserLoading, // 启动方法
|
||||
stopUserLoading // 停止方法
|
||||
} = useLoading('user', false);
|
||||
|
||||
// 手动控制 loading 状态
|
||||
const handleFetch = async () => {
|
||||
startUserLoading(); // 语义化启动
|
||||
|
||||
try {
|
||||
await fetchUserDataAPI();
|
||||
} catch (error) {
|
||||
console.error('获取用户数据失败', error);
|
||||
} finally {
|
||||
stopUserLoading(); // 语义化停止
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
userLoading,
|
||||
handleFetch
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
*/
|
||||
@@ -0,0 +1,79 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export function useRequest(name, service) {
|
||||
// 参数校验(保持不变)
|
||||
if (typeof name !== 'string' || !name.trim()) {
|
||||
throw new Error('useRequest: first argument "name" must be a non-empty string');
|
||||
}
|
||||
if (typeof service !== 'function') {
|
||||
throw new Error('useRequest: second argument "service" must be a function');
|
||||
}
|
||||
|
||||
const data = ref(null);
|
||||
const error = ref(null);
|
||||
const loading = ref(false);
|
||||
const capName = name.charAt(0).toUpperCase() + name.slice(1);
|
||||
|
||||
// ✅ 新增:纯 Promise 方法(不管理任何状态)
|
||||
const runAsync = (...args) => {
|
||||
return service(...args); // 直接返回原始 Promise
|
||||
};
|
||||
|
||||
// ✅ 优化:基于 runAsync 实现 run(避免逻辑重复)
|
||||
const run = async (...args) => {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
try {
|
||||
const result = await runAsync(...args); // ← 复用 runAsync
|
||||
data.value = result;
|
||||
return result;
|
||||
} catch (err) {
|
||||
error.value = err;
|
||||
throw err;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
[`${name}Data`]: data,
|
||||
[`${name}Error`]: error,
|
||||
[`${name}Loading`]: loading,
|
||||
[`fetch${capName}`]: run, // 自动管理状态
|
||||
[`fetch${capName}Async`]: runAsync // 纯 Promise 模式
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
✅ 测试用例 1:基础成功请求(run 模式)
|
||||
const mockService = () => Promise.resolve({ id: 1, name: "Test User" });
|
||||
|
||||
// 初始化 hook
|
||||
const { fetchUser, userData, userLoading, userError } =
|
||||
useRequest('user', mockService);
|
||||
|
||||
// 触发请求
|
||||
fetchUser();
|
||||
|
||||
// 验证结果
|
||||
console.log(userLoading.value); // true → false (自动切换)
|
||||
console.log(userData.value); // { id: 1, name: "Test User" }
|
||||
console.log(userError.value); // null
|
||||
|
||||
|
||||
✅ 测试用例 2:基础成功请求(runAsync 模式)
|
||||
const { fetchUserAsync, userData, userLoading } =
|
||||
useRequest('user', mockService);
|
||||
|
||||
// 仅执行请求,不修改内部状态
|
||||
fetchUserAsync().then(result => {
|
||||
console.log("Raw result:", result); // { id: 1, name: "Test User" }
|
||||
|
||||
// 关键验证:内部状态未被修改
|
||||
console.log(userLoading.value); // false (始终为 false)
|
||||
console.log(userData.value); // null (始终为 null)
|
||||
});
|
||||
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user