Vue3父子组件双向绑定后父组件watch监听对象不触发如何解决?
问题原因
- Vue默认的watch监听为浅层监听,仅会在被监听变量的引用本身发生替换时触发。你当前是修改
record对象的内部属性,record的引用没有变化,因此默认watch不会触发。 - 当前子组件直接修改props传入的对象属性,违反了Vue单向数据流规范,虽然因为对象是引用类型可以实现视图同步,但属于不符合规范的写法,后续维护容易出现不可预期的问题。
- 你父组件的
data写法存在语法错误,需要返回对象,否则record不会被正确声明为响应式属性。
解决方法
方案1:最小改动适配(快速生效)
给父组件的watch配置开启深度监听,同时修复data的语法错误:
<!-- parent.vue 修正后代码 --> <script lang="ts"> export default { data() { // 修正data返回对象的语法 return { record: undefined } }, created() { // 获取record的代码 this.record = new Record(responseJson); }, watch: { record: { handler: function(newRecord, oldRecord) { alert("change detected!"); // 子组件修改record时执行对应逻辑 }, // 开启深度监听,内部属性变更也会触发回调 deep: true } } } </script>
方案2:符合单向数据流规范的标准写法(更推荐)
子组件通过计算属性封装v-model逻辑,修改时主动抛出更新事件,符合Vue数据流向规范:
<!-- child.vue 修正后代码 --> <template> <InputText v-model="localRecord.title"></InputText> <InputText v-model="localRecord.description"></InputText> </template> <script lang="ts"> export default { props: { record: { type: Object as () => RecordModel, required: true } }, emits: ["update:record"], computed: { localRecord: { get() { return this.record }, set(val) { // 抛出更新事件,由父组件完成属性更新 this.$emit('update:record', val) } } } } </script>
该方案不需要额外开启深度监听,父组件的record引用会在子组件抛出事件时被替换,原生触发watch回调。
内容的提问来源于stack exchange,提问作者John D.
相关产品推荐
相关产品推荐

