组合式函数返回响应式数据须用 ref/reactive/computed 包裹,避免解构丢失响应性;推荐返回 ref 对象或 reactive 包裹的对象并用 torefs 解构;应集成 computed 和 watch 并提供类型定义。

在组合式函数(Composable)中返回响应式数据,核心是使用 ref、reactive 或 computed 等 Vue 3 响应式 API,并确保这些响应式对象被正确解构或暴露,不丢失响应性。关键不是“返回什么”,而是“如何返回才能保持响应式连接”。
用 ref/reactive 包裹数据再返回
直接返回普通对象或原始值会丢失响应性。必须用响应式包装器封装:
- 推荐用 ref 返回基础类型(如 number、string、boolean)或需要被解构使用的单个值;
- 用 reactive 返回结构较复杂的对象(如表单状态、配置集合),但注意它不能被解构——需通过属性访问;
- 避免在 composable 内部 return {...reactiveObj},这会剥除响应性;应 return { state } 或 return reactiveObj。
暴露响应式引用,而非解构后的值
常见错误:在调用方直接解构响应式对象,导致失去响应连接:
- ❌ 错误写法:
const { count, increment } = useCounter()—— 若 count 是 ref,解构后 count 变成普通 number,不再响应; - ✅ 正确写法:
const counter = useCounter(),模板中用{{ counter.count.value }};或返回 ref 并保持 .value 访问; - 更友好方案:组合式函数返回一个包含 ref 的对象,调用方用
toRefs安全解构(仅适用于 reactive 对象)。
配合 computed 和 watch 增强可复用性
高可复用的工具类不应只返回数据,还应提供计算属性和副作用控制能力:
- 用 computed 暴露派生状态(如
isDisabled: computed(() => loading.value || !formValid.value)); - 将 watch 逻辑内聚在 composable 中(如监听路由参数并刷新数据),避免调用方重复写副作用;
- 支持传入配置项(如默认值、节流时间),让同一工具适配不同场景。
导出函数 + 类型定义,提升 TypeScript 友好度
真正高可复用的组合式函数需兼顾类型推导:
- 为返回值添加明确的 interface 或 type,例如
interface UseCounterReturn { count: Ref<number>; increment: () => void }</number>; - 使用泛型支持灵活输入(如
useFetch<t></t>); - 在函数签名中标注返回类型,帮助 IDE 自动补全和类型检查。










