Vue SFC中defineEmits传值分三步:1.子组件用defineEmits声明事件签名;2.调用emit触发并传参;3.父组件用@监听事件接收数据;推荐TS类型安全,避免直接改props。

在 Vue 单文件组件(SFC)中使用 defineEmits 向父组件传值,核心是三步:声明可触发的事件、在子组件中调用 emit 触发并传参、父组件监听对应事件接收数据。整个过程不依赖 import,直接可用,且推荐配合 TypeScript 使用以获得类型安全。
1. 子组件中声明 defineEmits 并定义事件签名
在 <script setup> 中调用 defineEmits,明确告诉 Vue “本组件能发出哪些事件”以及“每个事件携带什么参数”。推荐使用 TS 泛型写法:
- 无参事件:
click: () => void - 单参事件:
'update-count': (newCount: number) => void - 多参或对象封装更清晰:
'submit-form': (data: { name: string; email: string }) => void
示例:
<script setup lang="ts">const emit = defineEmits<{
'update-count': (val: number) => void;
'submit-form': (data: { name: string; email: string }) => void;
}>();
</script>
2. 在子组件逻辑中调用 emit 触发事件
通过 emit('事件名', 参数) 主动通知父组件。注意:参数个数和类型必须严格匹配上一步声明的签名,否则 TypeScript 会报错。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
- 触发无参事件:
emit('click') - 触发带参事件:
emit('update-count', 100)或emit('submit-form', { name: '张三', email: 'zhang@example.com' }) - 常见场景如按钮点击、表单提交、接口响应后更新状态等,都在这里调用
3. 父组件监听事件并处理传入的数据
父组件在使用子组件时,用 @事件名 绑定处理函数。Vue 会把 emit 的第二个及后续参数自动赋给 $event(或解构为函数形参)。
- 简写方式:
@update-count="count = $event" - 函数方式:
@submit-form="handleFormSubmit",然后在setup中定义const handleFormSubmit = (data: { name: string; email: string }) => { ... } - 如果是
update:xxx格式事件(如update:modelValue),还可与v-model自动对接
4. 注意事项与最佳实践
避免踩坑,提高可维护性:
- 不要在子组件中直接修改 props,所有状态变更都应通过
emit通知父组件决定是否更新 - 事件命名建议语义化,如
add-item、delete-user;若用于同步某个 prop,则用update:xxx格式 - 多个参数建议封装为对象,比
emit('event', a, b, c, d)更易扩展和阅读 - 即使不用 TypeScript,也建议用数组形式声明事件名(
defineEmits(['submit', 'cancel'])),防止拼写错误

















