计算属性默认只读,需显式定义get和set方法实现可写;get返回派生值,set接收新值并更新源数据,从而支持双向绑定与响应式联动。

计算属性默认是只读的,当你尝试给它赋值时,Vue 会抛出 TypeError: Cannot set property xxx of #<object> which has only a getter</object> 这类错误。这不是 bug,而是设计使然——但 Vue 确实支持通过 setter 让计算属性“可写”,从而实现数据的双向拦截与响应式联动。
为什么计算属性默认只读?
计算属性(computed)本质是基于响应式依赖的缓存 getter 函数。它没有内置的写入逻辑,所以直接赋值会失败。只有显式定义了 set,Vue 才知道“当有人给这个计算属性赋值时,该做什么”。
如何正确添加 setter?
必须使用对象语法(而非函数语法)声明计算属性,并完整写出 get 和 set 方法:
- get:返回派生值(必填)
-
set:接收新值,内部应更新源数据(如
data或ref),不能直接修改计算属性自身
示例(Vue 2 / Vue 3 Options API):
computed: {
fullName: {
get() {
return this.firstName + ' ' + this.lastName;
},
set(newValue) {
const parts = newValue.split(' ');
this.firstName = parts[0] || '';
this.lastName = parts[1] || '';
}
}
}
在 Vue 3 Composition API 中,用 computed 函数配合 getter/setter 对象:
const fullName = computed({
get() {
return firstName.value + ' ' + lastName.value;
},
set(value) {
const [first, last] = value.split(' ');
firstName.value = first || '';
lastName.value = last || '';
}
});
常见错误与避坑点
- 只写了
set没写get→ 报错:“Computed property was assigned to but it has no setter” - 在
set中试图直接改this.fullName→ 无限递归或静默失败 - 源数据不是响应式的(比如普通对象属性未在
data中声明)→ setter 生效但视图不更新 - 对
ref使用computed时忘了加.value→ 值无法读取或写入
什么场景适合用 setter?
不是所有计算属性都需要可写。适合的典型场景包括:
- 表单字段聚合(如邮箱+密码 → loginForm 对象)
- 格式化输入(用户输入 “2024-05-20” → 自动拆解为 year/month/day)
- 封装复杂状态(如
isOnline计算属性,set 时触发重连逻辑) - 对接非响应式外部库(set 时调用其 API,get 时读取其状态)
本质上,setter 是你控制“外界怎么改内部状态”的一道门,不是为了绕过响应式规则,而是为了更自然地桥接不同数据形态。










