
在 vue 3 组合式 api 中,若子组件通过 `emit('update:xxx')` 通知父组件更新值,但父组件未正确监听该事件,则 prop 不会响应式更新;必须使用 `v-model:xxx` 语法替代手动绑定 `:xxx` 和 `@update:xxx`,才能实现真正的双向绑定。
你遇到的问题本质是 Vue 的响应式绑定机制未被正确激活:当前父组件仅通过 :show="abcdef" 单向传递 prop,却未订阅子组件发出的 update:show 事件——因此即使子组件调用 emit('update:show', false),父组件中的 abcdef 值也不会自动更新,导致 Dialog 持续显示。
✅ 正确做法是使用 Vue 3 的 v-model 语法糖(支持自定义参数):
父组件写法(修正后):
<template lang="pug">
Button(icon="pi pi-plus" @click="abcdef = true")
test(v-model:show="abcdef") <!-- ✅ 启用双向绑定 -->
</template>
<script setup>
import { ref } from 'vue'
import test from './mydialog.vue'
const abcdef = ref(false)
</script>子组件保持不变(但可优化):
你当前的子组件逻辑基本正确,但建议微调以提升健壮性:
<script setup>
import { ref, watch, defineEmits, defineProps } from 'vue'
const emit = defineEmits(['update:show'])
const props = defineProps({
show: { type: Boolean, default: false }
})
// 响应式同步 props.show → dShow(用于 Dialog visible)
const dShow = ref(props.show)
// 监听外部 prop 变化(如父组件直接修改 abcdef)
watch(() => props.show, (val) => {
dShow.value = val
})
// 关闭时通知父组件更新
const hide = () => {
emit('update:show', false)
}
</script>⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- v-model:show 是 :show="..." @update:show="..." 的语法糖,Vue 会自动将赋值操作映射为事件处理(即等价于 @update:show="(v) => abcdef.value = v");
- 子组件中 dShow 应初始化为 props.show(而非 false),避免首次渲染时状态错位;
- 若需支持 .sync 兼容或多个 v-model,可扩展为 v-model:visible、v-model:loading 等,命名需与 update:xxx 事件严格对应。
总结:Vue 3 的 v-model 不再是黑盒指令,而是基于约定的显式通信机制。只要子组件按 update:xxx 规范派发事件,父组件使用 v-model:xxx,即可零配置实现响应式双向绑定——无需额外 watch 或手动事件监听。










