Vue3中computed的set绑定对象v-model时失效如何解决?
问题原因与修复方案
为什么原来的set方法不触发?
你当前的写法里,computed的set方法只在直接对user整个对象赋值时才会触发(比如执行user = {name: 'xxx', age: 20}),但模板里绑定的是user.name和user.age——修改这些子属性时,只是在修改get返回的对象的内部值,并没有改变user这个computed引用本身,所以set完全不会被调用。
修复方案
方案1:给每个属性单独创建computed(适合属性少的场景)
如果你的user对象属性不多,直接给每个属性单独写computed,这样修改单个属性时就能触发对应的set逻辑:
<script setup> import { computed, defineProps, defineEmits } from 'vue' // 定义props和emit(实际场景中你应该已经配置) const props = defineProps({ user: { type: Object, default: () => ({ name: 'mike', age: 18 }) } }) const emit = defineEmits(['update:user']) // 针对name单独做computed const userName = computed({ get() { return props.user.name }, set(value) { // 生成新对象并通知父组件更新 emit('update:user', { ...props.user, name: value }) console.log('name更新为:', value) } }) // 针对age单独做computed const userAge = computed({ get() { return props.user.age }, set(value) { emit('update:user', { ...props.user, age: value }) console.log('age更新为:', value) } }) </script> <template> <input v-model="userName" type="text"> <input v-model="userAge" type="number"> </template>
方案2:用本地代理对象+深度监听(适合属性多的场景)
如果user属性很多,一个个写computed太麻烦,可以创建一个本地的响应式对象,同步props的值,再监听这个对象的变化来触发更新:
<script setup> import { ref, watch, defineProps, defineEmits } from 'vue' const props = defineProps({ user: { type: Object, default: () => ({ name: 'mike', age: 18 }) } }) const emit = defineEmits(['update:user']) // 创建本地响应式对象,初始同步props.user的值 const localUser = ref({ ...props.user }) // 监听props.user的变化,实时同步到本地对象 watch(() => props.user, (newUser) => { localUser.value = { ...newUser } }, { deep: true }) // 深度监听本地对象的所有属性变化,触发父组件更新 watch(localUser, (newUser) => { emit('update:user', newUser) console.log('user更新为:', newUser) }, { deep: true }) </script> <template> <input v-model="localUser.name" type="text"> <input v-model="localUser.age" type="number"> </template>
注意点
Vue中props是单向数据流,不能直接修改,所以不管哪种方案,最终都要通过emit把更新后的对象传给父组件,由父组件来修改原user数据。
内容的提问来源于stack exchange,提问作者Hao Sun
相关产品推荐
相关产品推荐

