Vue 3 模板中 ref 仅在顶层属性访问时自动解包(如 {{ count }}、v-show="visible"、prop 传递),而对象属性、数组索引、函数参数、运算表达式等场景不解包;模板禁止写 .value,应通过 computed 或结构调整避免嵌套。

在 Vue 3 模板中使用 ref 时,它会自动“解包”——即你不需要写 .value 就能访问其内部值。但这不是无条件的,有明确的规则和边界。
哪些情况会自动解包?
Vue 在模板中对 ref 的解包只发生在**顶层属性访问**场景下:
- 直接在插值表达式中使用:
{{ count }}(count是ref(0))→ 显示0 - 用在指令绑定中:
v-show="visible"(visible是ref(true))→ 正常生效 - 作为组件 prop 传递(非响应式穿透):
(message是ref('hello'))→ 子组件接收的是'hello',不是 ref 对象
哪些情况不会解包?
一旦 ref 被包裹或参与复杂操作,解包就失效,必须显式写 .value(但注意:这在模板中是不允许的):
- 作为对象属性访问:
{{ state.count }}(state是reactive({ count: ref(0) }))→ 不解包,得到的是 ref 对象本身 - 数组索引访问:
{{ list[0] }}(list是[ref(1), ref(2)])→ 不解包,输出[object Object] - 函数调用参数:
{{ format(count) }}→ 传入的是 ref 对象,不是它的值(除非函数内部处理.value) - 逻辑运算或赋值表达式:
{{ count + 1 }}→ 会触发toString(),结果通常是"[object Object]1",不是预期数字
为什么不能在模板里写 .value?
Vue 模板编译器禁止在插值或指令中出现 .value,因为这违背了“模板只负责视图描述”的设计原则。模板应保持声明式、简洁,而 .value 是响应式系统的底层细节。一旦你发现自己想写 {{ count.value }},说明 ref 的使用方式可能有问题:
- 该值本不该是 ref:基础类型数据(如字符串、数字、布尔)直接用
ref没问题;但若它天然属于某个响应式对象的一部分,优先用reactive或组合式computed - 嵌套过深:避免
reactive({ user: { profile: ref(...) } }),应扁平化结构或用computed封装读取逻辑 - 需要解包但又在复杂上下文中:改用
computed提前展开,例如const displayName = computed(() => user.name.value),再在模板中用{{ displayName }}
与 reactive 的配合要点
ref 和 reactive 可以混合使用,但要注意响应性“穿透”规则:
-
reactive内部的ref会被自动解包(仅限第一层):const state = reactive({ count: ref(0) }); state.count++→ 响应式更新 - 但
ref内部的reactive不会再被解包:const r = ref(reactive({ x: 1 }))→r.x是 undefined,必须用r.value.x - 安全做法:避免 ref 套 reactive;如需统一管理,用
reactive主导,基础字段直接赋值,无需额外 ref
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











