最直接方式是子组件用$emit触发自定义事件,父组件用@事件名监听;需显式声明事件、统一短横线命名、确保名称完全一致,避免拼写错误和异步时机错乱。
子组件向父组件传值,最直接的方式就是用 $emit 触发自定义事件,父组件通过 @事件名 监听并响应。这不是魔法,而是 Vue 明确约定的通信路径:子组件“喊话”,父组件“接话”。
必须先声明再触发,尤其在 setup 中需调用 defineEmits 显式定义事件列表,否则 TypeScript 报错、IDE 无提示、运行时也难排查。
submit-form),避免驼峰(submitForm)——HTML 模板中属性不区分大小写,驼峰会失效emit('submit-form', formData),支持传多个参数,父组件监听函数会按顺序接收emit,否则传的是空值或 undefined)监听名必须和 emit 的事件名完全一致(包括短横线、大小写),否则静默失败——控制台不报错,但逻辑不执行,这是调试中最容易卡住的点。
<child-component @submit-form="handleSave"></child-component>
@close-dialog="show = false")、或解构接收(@item-click="({ id, type }) => selectedId = id")v-model,本质仍是 $emit:Vue 3 是 update:modelValue,Vue 2 是 input;自定义 v-model 名(如 v-model:title)对应 update:title 事件这些不是边缘情况,而是日常开发里高频踩坑点:
emit('user-update'),父组件写成 @userUpdate → 不触发await api.submit() 前就 emit → 传的是初始值setup 中未调用 defineEmits → TypeScript 类型报错,且无法获得 IDE 补全methods 里漏了 handleSave,或拼成 handelSave → 控制台报 TypeError