Vue3中给可写计算属性赋值时为什么必须使用.value?
在Vue可写计算属性章节给出的示例代码如下:
<script setup> import { ref, computed } from 'vue' const firstName = ref('John') const lastName = ref('Doe') const fullName = computed({ // getter get() { return firstName.value + ' ' + lastName.value }, // setter set(newValue) { // 此处使用了解构赋值语法 [firstName.value, lastName.value] = newValue.split(' ') } }) </script>
该计算属性的正确赋值方式为:
fullName.value = 'John Doe'
问题解答
核心结论
不是。必须通过.value赋值的要求,和getter、setter内部是否使用ref()创建的响应式对象没有任何关系。
具体原因
- 不管是只读计算属性还是可写计算属性,
computed()的返回值本身就是一个标准的Ref类型实例,这个返回规则是固定的,和计算属性内部的逻辑无关。 - 所有
Ref类型的响应式数据,在<script>块的普通JavaScript逻辑里读写值,都必须通过.value属性操作。这是Ref的基础设计:JavaScript的原始类型不支持引用传递,Vue必须把值包裹在带.value属性的对象上,才能追踪值的读写动作,触发对应的响应式更新、以及你自定义的get/set逻辑。 - 如果直接给计算属性变量赋值(比如写
fullName = 'John Doe'),本质是直接覆盖了fullName变量的引用,你定义的setter根本不会被执行,自然不会生效,这和计算属性内部有没有用到其他ref没有关联。
反例验证
哪怕可写计算属性内部完全不依赖任何ref()创建的响应式对象,修改时依然必须走.value才能触发setter:
import { computed } from 'vue' // 内部完全没有使用ref const demo = computed({ get() { return window.__demo_val__ ?? 'init' }, set(newVal) { console.log('setter被触发,新值:', newVal) window.__demo_val__ = newVal } }) // 正确写法:触发setter,控制台打印日志 demo.value = 'test' // 错误写法:直接覆盖变量,setter完全不执行,没有任何效果 // demo = 'test'
补充说明
只有两种场景不需要写.value访问Ref:
- 在Vue模板中使用Ref时,Vue会自动做顶层解包
- 把Ref挂载到
reactive()创建的响应式对象属性上时,访问该属性会自动解包
内容的提问来源于stack exchange,提问作者Skeletor
相关产品推荐
相关产品推荐

