Vue3 + 组合式 API + 完整可运行 的 3 个超级常用通用 Hooks:useRequest、useClipboard、useStorage
1. useRequest —— 统一管理接口请求(最常用)
功能:
- 自动管理 data /loading/error
- 支持手动 / 自动执行
- 支持传参
- 支持异步函数
// src/hooks/useRequest.ts import { ref, onMounted } from 'vue' export function useRequest<T = any>( apiFn: (...args: any[]) => Promise<T>, options = { immediate: true } ) { const data = ref<T | null>(null) const loading = ref(false) const error = ref<Error | null>(null) const run = async (...args: any[]) => { loading.value = true error.value = null try { const res = await apiFn(...args) data.value = res return res } catch (err) { error.value = err as Error console.error('请求失败:', err) } finally { loading.value = false } } // 立即执行 if (options.immediate) { onMounted(() => run()) } return { data, loading, error, run } }<script setup lang="ts"> import { useRequest } from '@/hooks/useRequest' // 模拟接口 const getList = () => fetch('/api/list').then(res => res.json()) const { data, loading, error, run } = useRequest(getList) </script> <template> <div v-if="loading">加载中...</div> <div v-else-if="error">请求失败:{{ error.message }}</div> <div v-else>数据:{{ data }}</div> <button @click="run">刷新</button> </template>2. useClipboard —— 复制到剪贴板
功能:
- 复制文本
- 自动提示复制成功状态
- 兼容所有现代浏览器
// src/hooks/useClipboard.ts import { ref } from 'vue' export function useClipboard() { const copied = ref(false) const copy = async (text: string) => { try { await navigator.clipboard.writeText(text) copied.value = true setTimeout(() => (copied.value = false), 1500) } catch (err) { console.error('复制失败', err) } } return { copy, copied } }<script setup> import { useClipboard } from '@/hooks/useClipboard' const { copy, copied } = useClipboard() </script> <template> <button @click="copy('我是要复制的内容')"> {{ copied ? '复制成功' : '点击复制' }} </button> </template>3. useStorage —— 本地存储(localStorage /sessionStorage)
功能:
- 自动 JSON 序列化 / 反序列化
- 响应式
- 支持 localStorage /sessionStorage
- 支持删除
// src/hooks/useStorage.ts import { ref, watch } from 'vue' type StorageType = 'local' | 'session' export function useStorage<T>( key: string, defaultValue: T, type: StorageType = 'local' ) { const storage = type === 'local' ? localStorage : sessionStorage // 初始化 const read = () => { try { const item = storage.getItem(key) return item ? JSON.parse(item) : defaultValue } catch { return defaultValue } } const data = ref<T>(read()) // 监听变化自动保存 watch( data, (val) => { storage.setItem(key, JSON.stringify(val)) }, { deep: true } ) // 删除 const remove = () => { storage.removeItem(key) data.value = defaultValue } return { data, remove } }<script setup> import { useStorage } from '@/hooks/useStorage' // 存 localStorage const { data: userInfo, remove } = useStorage('userInfo', { name: '张三' }) // 存 sessionStorage // const { data } = useStorage('token', '', 'session') </script> <template> <div>{{ userInfo.name }}</div> <button @click="userInfo.name = '李四'">修改</button> <button @click="remove">删除</button> </template>// src/hooks/useModal.ts import { ref } from 'vue' export function useModal(initVisible = false) { const visible = ref(initVisible) const open = () => (visible.value = true) const close = () => (visible.value = false) const toggle = () => (visible.value = !visible.value) return { visible, open, close, toggle } }