Skip to content

为什么在 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 属性:始终自动解包。

这种设计大大简化了模板代码的编写,提高了开发体验,同时也兼顾了框架的执行效率。


🔗 相关推荐

最近更新