计算属性的 setter 是响应式数据桥梁,用于封装双向同步逻辑:getter 暴露 prop,setter 触发 update 事件(如 'input' 或 'update:xxx'),配合 v-model 或 .sync 实现父子组件数据同步。

计算属性的 setter 不是用于“直接通信”,而是作为 响应式数据桥梁,配合 props 和事件,在子组件内部封装双向同步逻辑。它本身不发送消息,但让子组件对传入 prop 的“修改”看起来像在操作本地数据,背后自动触发父组件更新。
核心原理:用 getter 暴露 prop,用 setter 触发 update 事件
Vue 中 props 是只读的,不能直接赋值。计算属性的 setter 提供了一个合法出口:当子组件代码试图“修改”这个计算属性时,setter 被调用,你可以在其中执行 this.$emit('input', newVal) 或 this.$emit('update:xxx', newVal),通知父组件该更新了。
父组件只要监听对应事件并更新自身数据,视觉上就实现了双向同步。
v-model 场景:value + input 的标准组合
这是最常见也最推荐的用法,适用于单个简单值(如字符串、数字、布尔):
- 子组件声明
props: ['value'] - 定义计算属性
syncValue,get()返回this.value,set(newVal)执行this.$emit('input', newVal) - 父组件使用
<child-component v-model="parentData"></child-component>
此时 v-model 自动展开为 :value="parentData" @input="val => parentData = val",无需额外写事件监听。
.sync 场景:支持任意 prop 名的更新协议
当需要同步的不是 value,而是比如 title、visible 等自定义字段时,用 .sync 更清晰:
- 子组件接收
props: ['title'] - 定义计算属性
syncTitle,get()返回this.title,set(newVal)执行this.$emit('update:title', newVal) - 父组件写
<child-component :title.sync="parentTitle"></child-component>
Vue 会自动把 :title.sync 编译成 :title="parentTitle" @update:title="val => parentTitle = val"。
复杂对象同步:Proxy + computed(需谨慎)
若父组件传入的是一个对象(如 user),想在子组件中直接修改 user.name 并同步回父组件,可借助 Proxy 封装:
- 计算属性
editableUser的get()返回一个 Proxy 对象,拦截set操作 - Proxy 的
set(target, key, value)中调用this.$emit('update:user', { ...target, [key]: value }) - 注意:这要求父组件能接收整个新对象并替换原对象,且需确保响应式不会丢失
这种写法灵活性高,但调试和维护成本上升,建议优先拆分为多个简单 prop 或改用 Vuex/Pinia 管理共享状态。










