Appearance
Kapitel 13: Watch & WatchEffect (Beobachter)
📙 Lernziel: watch() und watchEffect() meistern - Datenänderungen überwachen!
13.1 watch() Grundlagen
watch() überwacht reaktive Daten und führt bei Änderung eine Funktion aus.
Syntax:
javascript
watch(quelle, callback, optionen)Einfaches Beispiel:
vue
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const message = ref('Hallo')
// watch() - Überwacht count
watch(count, (newValue, oldValue) => {
console.log(`count geändert: ${oldValue} → ${newValue}`)
})
// watch() - Überwacht message
watch(message, (newValue, oldValue) => {
console.log(`message geändert: ${oldValue} → ${newValue}`)
})
// count erhöhen
const increment = () => {
count.value++
}
// message ändern
const changeMessage = () => {
message.value = 'Vue 3 ist toll!'
}
</script>
<template>
<p>Zähler: {{ count }}</p>
<button @click="increment">Erhöhen</button>
<p>Nachricht: {{ message }}</p>
<button @click="changeMessage">Nachricht ändern</button>
</template>Wichtig:
- ✅
watch()erhältnewValueundoldValue - ✅ Reagiert nur auf Änderungen der überwachten Quelle
13.2 watch() für mehrere Quellen
Mehrere Quellen gleichzeitig überwachen:
vue
<script setup>
import { ref, watch } from 'vue'
const firstName = ref('')
const lastName = ref('')
// Array von Quellen
watch([firstName, lastName], (newValues, oldValues) => {
console.log('Vorname oder Nachname geändert!')
console.log('Neu:', newValues)
console.log('Alt:', oldValues)
})
</script>
<template>
<div>
<label>Vorname: <input v-model="firstName" /></label><br>
<label>Nachname: <input v-model="lastName" /></label><br>
<p>Vollständiger Name: {{ firstName }} {{ lastName }}</p>
</div>
</template>13.3 watch() für Objekte (Tiefenüberwachung)
Problem: watch() überwacht standardmäßig nur Referenzänderungen.
Lösung: deep: true Option
vue
<script setup>
import { reactive, watch } from 'vue'
const user = reactive({
name: 'Max',
address: {
city: 'Berlin',
street: 'Hauptstraße'
}
})
// ❌ Funktioniert nicht für tiefe Änderungen
watch(user, () => {
console.log('user geändert')
})
// ✅ Mit deep: true
watch(user, () => {
console.log('user (tief) geändert')
}, { deep: true })
// ✅ Bessere Lösung: Nur spezifisches Property überwachen
watch(() => user.address.city, (newCity) => {
console.log('Stadt geändert:', newCity)
})
</script>
<template>
<div>
<p>Name: {{ user.name }}</p>
<p>Stadt: {{ user.address.city }}</p>
<button @click="user.address.city = 'München'">Stadt ändern</button>
</div>
</template>Empfehlung: Nutze () => user.address.city statt deep: true (effizienter)!
13.4 watchEffect() Grundlagen
watchEffect() führt eine Funktion sofort aus und überwacht alle darin verwendeten reaktiven Daten.
Unterschied zu watch():
| Merkmal | watch() | watchEffect() |
|---|---|---|
| Sofortige Ausführung | ❌ Nein | ✅ Ja |
| Explizite Quelle | ✅ Ja | ❌ Nein (automatisch) |
newValue / oldValue | ✅ Ja | ❌ Nein |
Beispiel:
vue
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
const message = ref('Hallo')
// watchEffect() - Führt sofort aus und überwacht Abhängigkeiten
watchEffect(() => {
console.log(`count: ${count.value}, message: ${message.value}`)
})
// count erhöhen
const increment = () => {
count.value++
}
// message ändern
const changeMessage = () => {
message.value = 'Vue 3 ist toll!'
}
</script>
<template>
<p>Zähler: {{ count }}</p>
<button @click="increment">Erhöhen</button>
<p>Nachricht: {{ message }}</p>
<button @click="changeMessage">Nachricht ändern</button>
</template>13.5 watch() vs watchEffect() - Wann was nutzen?
watch() nutzen wenn:
- ✅ Du brauchst
oldValueundnewValue - ✅ Du willst die Quelle explizit angeben
- ✅ Du willst nicht sofort ausführen (nur bei Änderung)
watchEffect() nutzen wenn:
- ✅ Du willst sofort ausführen
- ✅ Du hast mehrere Abhängigkeiten (automatische Erkennung)
- ✅ Du brauchst keine
oldValue
Beispiel - API Aufruf:
vue
<script setup>
import { ref, watch } from 'vue'
const userId = ref(1)
const userData = ref(null)
// watch() - API Aufruf nur wenn userId sich ändert
watch(userId, async (newId) => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${newId}`)
userData.value = await response.json()
}, { immediate: true }) // Sofort ausführen
</script>
<template>
<div>
<button @click="userId++">Nächster User</button>
<div v-if="userData">
<h2>{{ userData.name }}</h2>
<p>Email: {{ userData.email }}</p>
</div>
</div>
</template>13.6 Übung: Suchfeld mit watch()
Aufgabe: Erstelle ein Suchfeld, das bei Eingabe eine API abfragt (Debouncing).
Lösung:
vue
<script setup>
import { ref, watch } from 'vue'
const searchQuery = ref('')
const results = ref([])
const isLoading = ref(false)
let timeoutId = null
// watch() mit Debouncing
watch(searchQuery, (newQuery) => {
if (newQuery.trim() === '') {
results.value = []
return
}
// Debouncing: Warte 500ms vor API Aufruf
clearTimeout(timeoutId)
timeoutId = setTimeout(async () => {
isLoading.value = true
try {
const response = await fetch(`https://api.example.com/search?q=${newQuery}`)
results.value = await response.json()
} catch (error) {
console.error('Fehler:', error)
} finally {
isLoading.value = false
}
}, 500)
})
</script>
<template>
<div>
<input
v-model="searchQuery"
placeholder="Suchen..."
/>
<div v-if="isLoading">Lädt...</div>
<ul v-else>
<li v-for="result in results" :key="result.id">
{{ result.name }}
</li>
</ul>
</div>
</template>✅ Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅
watch()Grundlagen - ✅
watch()für mehrere Quellen - ✅
watch()für Objekte (deep: true) - ✅
watchEffect()Grundlagen - ✅ Unterschied zwischen
watch()undwatchEffect() - ✅ Praxis: Suchfeld mit Debouncing
🎯 Nächster Schritt: In Kapitel 14 lernst du Stilbindung (Class & Style)!
← Zurück zu Kapitel 12: Computed PropertiesWeiter zu Kapitel 14: Stilbindung →
