Appearance
Kapitel 17: Komponenten-Kommunikation (Teil 2) - Emits
📙 Lernziel: Daten von Kind- zu Eltern-Komponente mit defineEmits() übergeben!
17.1 Was sind Emits?
Emits (Events) senden Daten von Kind- zu Eltern-Komponente.
Datenfluss: Kind → Eltern (umgekehrt zu Props!)
Beispiel-Szenario:
App.vue (Eltern)
└─ MyButton.vue (Kind)
Sendet: click-Event mit Daten17.2 Emits definieren (defineEmits())
In Vue 3 (<script setup>):
vue
<!-- components/MyButton.vue -->
<script setup>
// Emits definieren (mit TypeScript)
defineEmits<{
(e: 'click', payload: string): void
(e: 'submit'): void
}>()
// Oder ohne TypeScript (Runtime-Validierung)
defineEmits({
click: [value: string], // Mit Payload
submit: null // Ohne Payload
})
</script>
<template>
<button @click="$emit('click', 'Hallo von Kind!')">
Klick mich!
</button>
<button @click="$emit('submit')">
Absenden
</button>
</template>
<style scoped>
button {
padding: 10px 20px;
background: #42b883;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>17.3 Emits abhören (Eltern-Komponente)
Verwendung in Eltern-Komponente:
vue
<!-- App.vue -->
<script setup>
import MyButton from './components/MyButton.vue'
const handleClick = (message) => {
alert('Vom Kind erhalten: ' + message)
}
const handleSubmit = () => {
console.log('Formular abgesendet!')
}
</script>
<template>
<div>
<h1>Meine App</h1>
<!-- Emit abhören (v-on:@) -->
<MyButton @click="handleClick" @submit="handleSubmit" />
<!-- Mit Inline-Funktion -->
<MyButton
@click="(msg) => console.log(msg)"
@submit="() => console.log('Submit')"
/>
</div>
</template>Wichtig:
- ✅
@click= Event-Listener fürclickEmit - ✅ Payload wird als Parameter übergeben
17.4 v-model mit Komponenten
v-model in Komponenten = props + emit Kombination:
vue
<!-- components/CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>Verwendung:
vue
<script setup>
import CustomInput from './components/CustomInput.vue'
import { ref } from 'vue'
const name = ref('')
</script>
<template>
<div>
<CustomInput v-model="name" />
<p>Name: {{ name }}</p>
</div>
</template>Vue 3 Shorthand:
vue
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<!-- Einfacher -->
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>17.5 Mehrere v-model bindungen
Vue 3 unterstützt mehrere v-model:
vue
<!-- components/UserForm.vue -->
<script setup>
defineProps(['name', 'email'])
defineEmits(['update:name', 'update:email'])
</script>
<template>
<div>
<input
:value="name"
@input="$emit('update:name', $event.target.value)"
placeholder="Name"
/>
<input
:value="email"
@input="$emit('update:email', $event.target.value)"
placeholder="Email"
/>
</div>
</template>Verwendung:
vue
<script setup>
import UserForm from './components/UserForm.vue'
import { ref } from 'vue'
const userName = ref('')
const userEmail = ref('')
</script>
<template>
<UserForm
v-model:name="userName"
v-model:email="userEmail"
/>
<p>Name: {{ userName }}, Email: {{ userEmail }}</p>
</template>17.6 Übung: Counter-Komponente
Aufgabe: Erstelle eine Counter.vue Komponente mit Emit.
Lösung:
vue
<!-- components/Counter.vue -->
<script setup>
import { ref } from 'vue'
const count = ref(0)
defineEmits(['update:count', 'reset'])
const increment = () => {
count.value++
emit('update:count', count.value)
}
const decrement = () => {
count.value--
emit('update:count', count.value)
}
const reset = () => {
count.value = 0
emit('reset')
}
</script>
<template>
<div class="counter">
<h3>Zähler: {{ count }}</h3>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="reset">Zurücksetzen</button>
</div>
</template>
<style scoped>
.counter {
border: 1px solid #ddd;
padding: 15px;
margin: 10px;
max-width: 300px;
}
button {
margin: 0 5px;
padding: 5px 10px;
}
</style>Verwendung in App.vue:
vue
<script setup>
import Counter from './components/Counter.vue'
import { ref } from 'vue'
const currentCount = ref(0)
const handleReset = () => {
console.log('Zähler wurde zurückgesetzt!')
}
</script>
<template>
<Counter
v-model:count="currentCount"
@reset="handleReset"
/>
<p>Aktueller Zählerwert: {{ currentCount }}</p>
</template>✅ Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Was Emits sind (Kind → Eltern)
- ✅
defineEmits()nutzen - ✅ Emits abhören (
@event) - ✅
v-modelmit Komponenten - ✅ Mehrere
v-modelbindungen - ✅ Praxis:
Counter.vueKomponente
🎯 Nächster Schritt: In Kapitel 18 lernst du provide/inject - Vorfahren → Nachkommen!
← Zurück zu Kapitel 16: PropsWeiter zu Kapitel 18: Provide & Inject →
