Vue/React 逻辑提取为可复用 Composable/Hook
将组件内的业务逻辑提取为独立的 Composable (Vue) 或 Hook (React),实现逻辑复用、测试解耦
提示词
你是前端架构师。任务:将组件内耦合的逻辑提取为可复用的 Composable/Hook。
约束:
- 识别可复用逻辑:状态管理、副作用、计算属性、生命周期
- Vue: useXxx.ts 导出函数,内部用 ref/computed/watch/onMounted
- React: useXxx.ts 导出函数,内部用 useState/useEffect/useMemo/useCallback
- 类型安全:泛型参数、返回值接口、Props 接口
- 无副作用初始化:仅声明,调用时才执行
- 支持多实例:每次调用返回独立状态
- 测试友好:纯函数核心逻辑、依赖注入外部服务
- 输出:Composable/Hook 文件 + 使用示例 + 单测模板
输出格式:
// useUserProfile.ts (Vue)
// useUserProfile.ts (React)
// useUserProfile.test.ts
少样本示例
展示 Vue Composable 提取、响应式状态、生命周期、watch、类型导出
输入
// Vue 组件内逻辑
<script setup lang="ts"> | const user = ref<User | null>(null); | const loading = ref(false); | const error = ref<string | null>(null); | async function loadUser(id: string) { loading.value = true; error.value = null; try { user.value = await fetchUser(id); } catch (e) { error.value = e.message; } finally { loading.value = false; } } onMounted(() => loadUser(props.userId)); watch(() => props.userId, loadUser); </script>输出
// composables/useUserProfile.ts (Vue)
import { ref, watch, onMounted } from 'vue';
import { fetchUser } from '@/api/user';
export interface UserProfileState {
| user: Ref<User | null>; |
loading: Ref<boolean>;
| error: Ref<string | null>; |
loadUser: (id: string) => Promise<void>;
}
export function useUserProfile(initialId?: string): UserProfileState {
| const user = ref<User | null>(null); |
const loading = ref(false);
| const error = ref<string | null>(null); |
async function loadUser(id: string) {
loading.value = true;
error.value = null;
try {
user.value = await fetchUser(id);
} catch (e) {
error.value = e instanceof Error ? e.message : 'Unknown error';
} finally {
loading.value = false;
}
}
if (initialId) {
onMounted(() => loadUser(initialId));
}
return { user, loading, error, loadUser };
}
// 组件中使用
<script setup lang="ts"> import { useUserProfile } from '@/composables/useUserProfile'; const { user, loading, error, loadUser } = useUserProfile(props.userId); watch(() => props.userId, loadUser); </script>