ref 是组合式 API 中最基础的响应式创建函数,用于使普通 JavaScript 值具备响应能力并在模板中自动解包;它通过显式 .value 访问与隐式模板解包实现逻辑关注点分离,支持单一职责封装、自定义 Hook 组合及 toRefs 安全解构,与 reactive 各司其职。

ref 是组合式 API 中最基础的响应式创建函数,它让普通 JavaScript 值(如字符串、数字、布尔值、对象甚至 null)具备响应能力,并在模板中自动解包,是实现逻辑关注点分离的起点。
ref 为什么是逻辑分离的第一步
使用 ref 创建的状态变量天然隔离了数据定义与使用场景。你可以在一个独立的函数或文件中封装某个功能模块所需的所有响应式状态和相关逻辑,不依赖组件实例,也不污染全局作用域。
- 每个 ref 变量只负责单一职责(比如
searchQuery = ref('')专注处理搜索关键词) - 多个 ref 可组合进同一个自定义 Hook(如
useSearch()),把“搜索”这个关注点完整抽离 - 组件中只需调用 Hook 并解构使用,无需关心内部如何响应更新
ref 在 setup 中的实际用法要点
在 setup() 函数里,ref 创建的值必须通过 .value 访问和修改,但在模板中会自动解包 —— 这个“显式读写、隐式使用”的设计,恰恰强化了逻辑边界。
- 在 JS 中:要读取写入都用
count.value++,避免误当普通变量操作 - 在模板中:
{{ count }}就行,Vue 自动处理解包,不用写.value - 响应式不是魔法:只有被 ref(或 reactive)包装过的值才触发更新,原始值赋值不会响应
配合 toRefs 实现更干净的解构导出
当一个组合函数返回多个 ref,直接解构会丢失响应性。用 toRefs 可以把响应式对象的每个属性转为独立的 ref,既保持响应,又支持 ES6 解构,让组件使用更直观。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
const { count, name } = useCounter()→ 解构后不再是 ref,失去响应 - 正确写法:
const { count, name } = toRefs(useCounter())→ 每个都是 ref,可直接传给子组件或在模板使用 - 也可在自定义 Hook 内部就用 toRefs 包裹返回值,对外提供“即取即用”的响应式字段
ref 与 reactive 的分工建议
别强行统一用某一种。ref 更适合基础类型和需要明确标识响应性的单值;reactive 更适合已有结构的对象。二者可共存、可嵌套,关键看语义是否清晰。
- 用
ref:计数器数值、开关状态、输入框内容、API 加载标志等原子级状态 - 用
reactive:表单整体数据、用户信息对象、配置项集合等结构化数据 - ref 里也可以放 reactive 对象:
const userInfo = ref(reactive({ name: '', age: 0 })),适用于需整体替换的场景


















