vue3中defineEmits的使用说明
一、基本用法
-
声明事件
使用defineEmits定义组件可触发的事件,返回一个emit函数用于触发事件:vue
<script setup> const emit = defineEmits(['submit', 'update:value']) </script>
const emit = defineEmits(["update:modelValue"]);
-
触发事件
在需要的地方调用emit(eventName, ...args):javascript
function handleSubmit() {emit('submit', { data: 'example' }) }
二、类型检查(TypeScript)
通过泛型参数定义事件签名,增强类型安全:
vue
<script setup lang="ts">
const emit = defineEmits<{(e: 'submit', payload: { data: string }): void(e: 'update:value', id: number): void
}>()
</script>
const emit = defineEmits<{(evt: "handleApplyItemSelectionChange", data: ApplyItem[]): void;(evt: "handleApplyItemXSelectionChange", data: ApplyItem[]): void;
}>();const emit = defineEmits<{handleApplyItemSelectionChange: [data: ApplyItem[]];handleApplyItemXSelectionChange: [data: ApplyItem[]];
}>();
或使用更简洁的语法(Vue 3.3+):
typescript
defineEmits<{submit: [payload: { data: string }]'update:value': [id: number]
}>()
const emit = defineEmits<{"update:modelValue": [value: ApplyBasicInfo];
}>();
三、示例场景
1. 表单提交
vue
<script setup>
const emit = defineEmits(['submit'])function onSubmit() {emit('submit', { username: 'user', password: 'pass' })
}
</script><template><form @submit.prevent="onSubmit"><!-- 表单内容 --></form>
</template>
2. 更新父组件状态
vue
<script setup>
const emit = defineEmits(['update:count'])function increment() {emit('update:count', 10) // 通知父组件更新 count
}
</script>
四、注意事项
-
命名规范
建议使用 kebab-case(如update:value),因 HTML 属性不区分大小写。 -
验证事件参数
可在defineEmits中定义类型(TypeScript)或在 Options API 的emits选项添加验证函数:javascript
// Options API 验证 emits: {submit: (payload) => !!payload.data } -
与 Options API 对比
-
<script setup>中用defineEmits替代emits选项。 -
类型推断更直观,适合 TypeScript。
-
-
无
<script setup>时的用法
需改用 Options API 的emits选项:javascript
export default {emits: ['submit'],setup(props, { emit }) {// 使用 emit('submit')} }
五、总结
-
defineEmits用于在组合式 API 中声明组件事件。 -
通过类型泛型(TS)或数组(JS)定义事件列表。
-
触发事件:
emit('event-name', payload) -
优势:明确的类型检查和更好的代码可维护性。
在 Vue 3 + TypeScript 中,使用 defineEmits 可以为组件定义强类型的事件。以下是几种常见的使用方式:
基础示例
vue
<script setup lang="ts">
// 子组件 ChildComponent.vue
const emit = defineEmits<{// 无参数事件(e: 'click'): void// 带参数事件(e: 'submit', payload: { email: string; password: string }): void// 可选参数事件(e: 'update', value?: number): void
}>()// 触发事件
const handleClick = () => emit('click')
const handleSubmit = () => emit('submit', { email: 'test@a.com', password: '123' })
</script>
更简洁的类型声明(Vue 3.3+ 推荐)
vue
<script setup lang="ts">
// 使用 TypeScript 接口定义事件
interface Emits {(e: 'change', value: string): void(e: 'toggle', checked: boolean): void
}const emit = defineEmits<Emits>()// 触发事件
emit('change', 'new value')
emit('toggle', true)
</script>
结合运行时验证(可选)
vue
<script setup lang="ts">
const emit = defineEmits({// 运行时验证函数submit: (payload: { email: string }) => {if (!payload.email.includes('@')) {console.warn('Invalid email format')return false}return true // 返回 true 表示验证通过}
})// 触发事件(如果验证失败,控制台会警告)
emit('submit', { email: 'test@a.com' })
</script>
父组件调用示例
vue
<!-- 父组件 ParentComponent.vue -->
<template><ChildComponent @click="handleChildClick"@submit="handleChildSubmit"/>
</template><script setup lang="ts">
const handleChildClick = () => {console.log('收到点击事件')
}const handleChildSubmit = (payload: { email: string; password: string }) => {console.log('收到提交数据:', payload)
}
</script>
注意事项
-
类型安全:使用 TypeScript 接口/类型定义事件参数,确保触发事件时传递正确的参数类型
-
Vue 版本:类型声明语法需要 Vue 3.3+ 版本支持
-
两种风格:
-
纯类型声明(
defineEmits<{...}>())提供更好的 TS 支持 -
运行时声明(
defineEmits({...}))可以添加验证逻辑
-
-
事件命名:推荐使用 camelCase 事件名(Vue 会自动转换为 kebab-case 在模板中使用)
通过这种方式,可以在组件间获得完整的类型提示和校验,提升代码可靠性。
