组合式函数必须返回 ref、reactive、computed 或绑定响应式状态的函数,确保响应性不丢失;禁止直接解构返回普通值或未包装的原始类型。

组合式函数(Composable)向外暴露响应式状态和操作方法,核心原则是:返回一个包含 ref、reactive、computed 或 函数 的对象,且所有值都保持响应式连接。Vue 不会自动“提升”普通变量为响应式,必须显式使用响应式 API 创建并返回。
暴露响应式状态的正确方式
不能直接返回解构后的属性(会丢失响应性),也不能返回普通对象或原始值。必须返回由 ref、reactive 或 computed 创建的响应式实体:
- 用
ref包裹基础类型(如count、loading、error),返回count(不是count.value) - 用
reactive包裹对象,返回整个对象(如form、user),不要解构后返回字段 - 若需解构对象属性又保留响应性,先用
toRefs转换:return { ...toRefs(state) } - 计算属性用
computed创建后直接返回,如fullName,模板中可像 ref 一样直接使用
暴露操作方法的注意事项
方法本身无需特殊处理,但必须满足两个条件才能在组件中正常调用:
- 函数需定义在组合式函数内部,并通过 return 暴露(如
submit、reset) - 函数体内访问的状态必须是响应式来源(
ref.value或reactive对象属性),否则无法触发更新 - 避免在方法中直接修改解构出的普通变量(如
const { count } = toRefs(state)后写count++无效),应始终通过count.value++或state.count++ - 异步操作(如 API 调用)中更新状态,要确保在响应式引用上赋值,例如
data.value = await api.get()
完整示例:useCounter 组合式函数
这是一个典型可复用组合式函数,同时暴露状态与方法:
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
import { ref, computed } from 'vue'
<p>export function useCounter(initial = 0) {
const count = ref(initial)
const double = computed(() => count.value * 2)</p><p>const increment = () => count.value++
const decrement = () => count.value--
const reset = () => count.value = initial</p><p>// ✅ 正确暴露:全部为响应式实体或绑定上下文的函数
return {
count, // ref,模板中 {{ count }} 自动解包
double, // computed,只读响应式
increment, // 普通函数,闭包持有 count 引用
decrement,
reset
}
}</p>
在组件中使用时,直接解构即可,所有成员保持响应性和行为完整性。
不推荐的暴露方式
以下做法会导致响应性断裂或逻辑失效:
- 返回解构对象:
const { count } = reactive({ count: 0 }); return { count }→count是普通数字,无响应性 - 返回普通函数但未绑定状态:
return { getCount: () => count }(count是局部变量而非 ref) - 在组合式函数外创建 ref 并传入,再返回该 ref —— 破坏封装性,也易引发意外共享
- 暴露未包装的 Promise 或原始数组/对象,期望它自动变响应式(不会)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









