Tak jak propsy definiują dane wejściowe komponentu, emity definiują zdarzenia wyjściowe. W TypeScript możemy precyzyjnie typować jakie zdarzenia komponent emituje i jakie dane niesie każde zdarzenie.
1<script setup lang="ts">
2// Składnia generyczna
3const emit = defineEmits<{
4 (e: 'update', value: string): void
5 (e: 'delete', id: number): void
6 (e: 'close'): void
7}>()
8
9// Użycie
10emit('update', 'new value') // OK
11emit('delete', 42) // OK
12emit('close') // OK
13// emit('update', 123) // BŁĄD! Oczekiwany string, nie number
14// emit('unknown') // BŁĄD! Nieznane zdarzenie
15</script>Od Vue 3.3 dostępna jest krótsza składnia:
1<script setup lang="ts">
2const emit = defineEmits<{
3 update: [value: string]
4 delete: [id: number]
5 close: []
6}>()
7</script>Obie składnie są równoważne. Nowa jest bardziej zwięzła — używamy nazwy zdarzenia jako klucza, a argumenty jako krotki (tuple).
Oto przykład panelu sterowania stacją:
1<script setup lang="ts">
2interface ModuleEvent {
3 moduleId: string
4 timestamp: number
5}
6
7const emit = defineEmits<{
8 activate: [event: ModuleEvent]
9 deactivate: [event: ModuleEvent]
10 alert: [level: 'low' | 'medium' | 'high', message: string]
11}>()
12
13function handleActivation(moduleId: string) {
14 emit('activate', {
15 moduleId,
16 timestamp: Date.now()
17 })
18}
19
20function triggerAlert() {
21 emit('alert', 'high', 'Anomalia kwantowa wykryta!')
22}
23</script>Komponent dziecko emituje zdarzenia, rodzic nasłuchuje:
1<!-- ControlPanel.vue (dziecko) -->
2<script setup lang="ts">
3const emit = defineEmits<{
4 command: [action: string, target: string]
5}>()
6</script>
7
8<template>
9 <button @click="emit('command', 'scan', 'sector-7')">
10 Skanuj Sektor 7
11 </button>
12</template>1<!-- App.vue (rodzic) -->
2<template>
3 <ControlPanel @command="handleCommand" />
4</template>
5
6<script setup lang="ts">
7function handleCommand(action: string, target: string) {
8 console.log(action, target)
9 // TypeScript zna typy argumentów!
10}
11</script>Wzorzec v-model z typami:
1<script setup lang="ts">
2const props = defineProps<{
3 modelValue: string
4}>()
5
6const emit = defineEmits<{
7 'update:modelValue': [value: string]
8}>()
9
10function onInput(event: Event) {
11 const target = event.target as HTMLInputElement
12 emit('update:modelValue', target.value)
13}
14</script>
15
16<template>
17 <input :value="modelValue" @input="onInput" />
18</template>