
在 vue 3 组合式 api 中,子组件通过 `emit('update:propname')` 通知父组件更新 prop 时,父组件必须使用 `v-model:propname` 语法(而非静态 `:propname`)才能实现响应式双向绑定,否则父级状态不会自动更新。
你遇到的问题根源在于:父组件使用了单向绑定 :show="abcdef",却期望子组件通过 emit('update:show') 触发父级状态更新——这在 Vue 中不会自动生效。Vue 的 update: 事件机制本身是“被动通知”,它不会自动修改父组件的数据;真正驱动双向同步的是 v-model 语法糖。
✅ 正确做法:使用 v-model:show
将父组件中的调用从:
test(:show="abcdef")
改为:
test(v-model:show="abcdef")
此时 Vue 会自动将其编译为等价于:
立即学习“前端免费学习笔记(深入)”;
test(:show="abcdef" @update:show="val => abcdef.value = val")
即自动注册监听器,将子组件发出的 update:show 事件映射为对 abcdef 响应式引用的赋值操作。
? 子组件可进一步优化(非必需但推荐)
当前子组件中 watch 手动同步 props.show → dShow 是合理的,但注意:dShow 仅用于控制 Dialog 的 :visible 属性,而 Dialog 组件本身也支持 v-model:visible。因此更简洁、语义更清晰的写法是直接绑定 v-model:visible:
Dialog(
v-model:visible="props.show"
:modal="true"
:draggable="false"
header="My Dialog"
:style="{ width: '50vw' }"
)
p test
template(#footer)
Button(label="Test")
⚠️ 注意:此优化前提是所用 PrimeVue 版本 ≥ 3.27(支持 v-model:visible)。若版本较旧,请保留原 watch + ref 方案,并务必确保父组件使用 v-model:show。
? 总结关键点
- :prop="value" 是单向绑定,子组件无法反向影响父值;
- v-model:prop="value" 是双向绑定语法糖,自动处理 :prop 和 @update:prop;
- 自定义事件名必须严格匹配 update:xxx 格式,且 xxx 需与 v-model:xxx 中的修饰符一致;
- 父组件中 ref 值(如 abcdef)必须是响应式对象(ref() 创建),才能被 v-model 正确赋值。
遵循以上规则,点击 Dialog 关闭图标后,hide() 触发 emit('update:show', false),父组件 abcdef 将实时更新为 false,Dialog 自然隐藏。










