为什么在 template 里不需要 .value?
在 Vue 3 的 Composition API 中,我们通常使用 ref 来创建响应式数据。在 JavaScript 代码中,我们需要通过 .value 来访问或修改它的值,但在 <template> 中却可以直接使用,不需要 .value。
这是因为 Vue 的模板编译器在处理模板时,会自动对响应式引用(Refs)进行“解包”(Unwrapping)处理。
1. 自动解包机制 (Template Unwrapping)
当一个 ref 在模板中作为顶层属性被访问时,Vue 会自动调用 unref()。
示例
javascript
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count // 顶层属性
}
}
}在模板中:
html
<!-- 这里的 count 自动解包,等同于 count.value -->
<template>
<div>{{ count }}</div>
</template>2. 只有顶层属性会触发自动解包
这是一个非常重要的细节。如果 ref 不是作为模板渲染上下文的顶层属性,而是嵌套在对象中,那么它不会被自动解包。
错误示例
javascript
const state = {
count: ref(0) // 嵌套在普通对象中
}
return { state }在模板中:
html
<!-- 这里的 count 不会自动解包,显示的是 [object Object] -->
<p>{{ state.count }}</p>
<!-- 必须手动访问 .value -->
<p>{{ state.count.value }}</p>3. 为什么会有这种限制?
这种设计是为了保持性能和逻辑的清晰。
- 性能:如果 Vue 递归地检查模板中引用的每个对象的每个属性是否为
ref,会带来巨大的运行时开销。 - 一致性:顶层属性的解包是由模板编译器在生成渲染函数时静态注入的。
4. 特殊情况:reactive 对象的属性
如果一个 ref 是作为 reactive 对象的属性,它也会被自动解包,无论在代码还是模板中。
javascript
const count = ref(0)
const state = reactive({
count // 这里会自动解包
})
console.log(state.count) // 0,不需要 .value但在模板中,如果你通过解构 reactive 对象得到的变量,依然遵循“顶层属性”原则。
5. 总结
- 顶层 ref:在
<template>中自动解包,无需.value。 - 非顶层 ref(嵌套在普通对象中):需要手动写
.value。 - reactive 属性:始终自动解包。
这种设计大大简化了模板代码的编写,提高了开发体验,同时也兼顾了框架的执行效率。
🔗 相关推荐
- 深入理解 setup:了解 setup 的执行时机、参数及与模板的关系,请参阅 Vue3 setup 深入解析与原理解析。