Computed & Watchers
Computed Properties
Abschnitt betitelt „Computed Properties“Computed Properties sind abgeleitete Werte, die automatisch neu berechnet werden, wenn sich ihre Abhängigkeiten ändern.
Sie sind ideal für komplexe Berechnungen oder Transformationen, die von reaktiven Daten abhängen.
Warum nicht Methods?
Abschnitt betitelt „Warum nicht Methods?“<script setup>import { ref, computed } from 'vue'
const firstName = ref('Max')const lastName = ref('Mustermann')
// Method: Wird bei JEDEM Render aufgerufenfunction getFullName() { console.log('Method aufgerufen') return firstName.value + ' ' + lastName.value}
// Computed: Wird nur bei Änderung neu berechnet (gecached)const fullName = computed(() => { console.log('Computed aufgerufen') return firstName.value + ' ' + lastName.value})</script>Composition API
Abschnitt betitelt „Composition API“<script setup>import { ref, computed } from 'vue'
const items = ref([ { name: 'Apfel', price: 1.50, quantity: 3 }, { name: 'Birne', price: 2.00, quantity: 2 }])
// Einfaches Computedconst itemCount = computed(() => items.value.length)
// Computed mit Logikconst totalPrice = computed(() => { return items.value.reduce((sum, item) => { return sum + item.price * item.quantity }, 0)})
// Computed für Filterungconst expensiveItems = computed(() => { return items.value.filter(item => item.price > 1.50)})</script>Options API
Abschnitt betitelt „Options API“<script>export default { data() { return { firstName: 'Max', lastName: 'Mustermann', items: [] } }, computed: { fullName() { return this.firstName + ' ' + this.lastName }, itemCount() { return this.items.length }, totalPrice() { return this.items.reduce((sum, item) => sum + item.price, 0) } }}</script>Writable Computed (Getter/Setter)
Abschnitt betitelt „Writable Computed (Getter/Setter)“Standardmäßig sind Computed Properties read-only. Mit Getter und Setter werden sie beschreibbar:
<script setup>import { ref, computed } from 'vue'
const firstName = ref('Max')const lastName = ref('Mustermann')
const fullName = computed({ get() { return firstName.value + ' ' + lastName.value }, set(newValue) { const parts = newValue.split(' ') firstName.value = parts[0] lastName.value = parts[1] || '' }})
// Jetzt möglich:fullName.value = 'Anna Schmidt' // Setzt firstName und lastName</script>Best Practices
Abschnitt betitelt „Best Practices“- Abgeleitete Daten
- Formatierung (Datum, Währung)
- Filterung & Sortierung
- Komplexe Bedingungen im Template
- Side Effects (API Calls, DOM)
- Async Operationen
- Mutation von anderen States
- Zufällige Werte (
Math.random())
Watchers
Abschnitt betitelt „Watchers“Watchers beobachten reaktive Daten und führen Code aus, wenn sich diese ändern.
Sie sind ideal für Side Effects wie API-Aufrufe, DOM-Manipulationen oder das Synchronisieren mit externen Systemen.
watch()
Abschnitt betitelt „watch()“<script setup>import { ref, watch } from 'vue'
const searchQuery = ref('')const searchResults = ref([])
// Einzelne Ref beobachtenwatch(searchQuery, async (newValue, oldValue) => { console.log(`Suche geändert: ${oldValue} -> ${newValue}`)
if (newValue.length >= 3) { searchResults.value = await fetchResults(newValue) }})</script>Mehrere Quellen beobachten
Abschnitt betitelt „Mehrere Quellen beobachten“<script setup>import { ref, reactive, watch } from 'vue'
const firstName = ref('Max')const lastName = ref('Mustermann')
// Array von Quellenwatch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => { console.log(`Name: ${oldFirst} ${oldLast} -> ${newFirst} ${newLast}`)})
// Reactive Object Property (Getter-Funktion nötig!)const user = reactive({ name: 'Max' })
watch( () => user.name, // Getter-Funktion (newName) => { console.log('Name geändert:', newName) })</script>watch() Optionen
Abschnitt betitelt „watch() Optionen“<script setup>import { ref, watch } from 'vue'
const data = ref({ nested: { value: 0 } })
watch(data, (newData) => { console.log('Data geändert')}, { // Sofort beim Setup ausführen (nicht auf Änderung warten) immediate: true,
// Tief verschachtelte Änderungen beobachten deep: true,
// Callback nach DOM-Update ausführen flush: 'post',
// Nur einmal ausführen once: true})</script>Deep Watching
Abschnitt betitelt „Deep Watching“<script setup>import { ref, reactive, watch } from 'vue'
// Mit ref() - deep: true erforderlichconst user = ref({ profile: { name: 'Max', age: 30 }})
watch(user, (newUser) => { console.log('User geändert')}, { deep: true })
// Mit reactive() - automatisch deep!const state = reactive({ user: { name: 'Max' }})
watch(state, (newState) => { console.log('State geändert') // Automatisch deep})</script>watchEffect()
Abschnitt betitelt „watchEffect()“watchEffect() trackt Abhängigkeiten automatisch und führt sofort aus:
<script setup>import { ref, watchEffect } from 'vue'
const url = ref('/api/users')const data = ref(null)
// Führt sofort aus UND bei jeder Änderung von urlwatchEffect(async () => { const response = await fetch(url.value) data.value = await response.json()})
// Cleanup-FunktionwatchEffect((onCleanup) => { const controller = new AbortController()
fetch(url.value, { signal: controller.signal }) .then(r => r.json()) .then(d => data.value = d)
onCleanup(() => controller.abort())})</script>watch() vs watchEffect()
Abschnitt betitelt „watch() vs watchEffect()“| Aspekt | watch() | watchEffect() |
|---|---|---|
| Abhängigkeiten | Explizit angeben | Automatisch getrackt |
| Ausführung | Bei Änderung | Sofort + bei Änderung |
| Alter Wert | Verfügbar | Nicht verfügbar |
| Lazy | Standard | Immer eager |
| Präzision | Gezielt | Alle genutzten Refs |
Options API
Abschnitt betitelt „Options API“<script>export default { data() { return { searchQuery: '', user: { name: 'Max' } } }, watch: { // Einfacher Watcher searchQuery(newValue, oldValue) { console.log('Suche:', newValue) },
// Mit Optionen user: { handler(newUser) { console.log('User geändert') }, deep: true, immediate: true } }}</script>Watcher stoppen
Abschnitt betitelt „Watcher stoppen“<script setup>import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
// watch() und watchEffect() geben eine Stop-Funktion zurückconst stopWatch = watch(count, (newCount) => { console.log('Count:', newCount)
// Automatisch stoppen bei Bedingung if (newCount >= 10) { stopWatch() }})
// Manuell stoppensetTimeout(() => { stopWatch()}, 5000)</script>Computed vs Watch: Wann was?
Abschnitt betitelt „Computed vs Watch: Wann was?“- Abgeleitete Daten berechnen
- Synchrone Operationen
- Gecachter Rückgabewert
- Pure Funktionen
const fullName = computed(() => first.value + ' ' + last.value)- Side Effects ausführen
- Async Operationen
- Auf Änderungen reagieren
- Alter & neuer Wert vergleichen
watch(userId, async (id) => { user.value = await fetchUser(id)})Praktisches Beispiel: Debounced Search
Abschnitt betitelt „Praktisches Beispiel: Debounced Search“<script setup>import { ref, watch } from 'vue'
const searchQuery = ref('')const results = ref([])const isLoading = ref(false)
let timeout = null
watch(searchQuery, (query) => { // Vorherigen Timer abbrechen clearTimeout(timeout)
if (query.length < 2) { results.value = [] return }
// Debounce: 300ms warten timeout = setTimeout(async () => { isLoading.value = true results.value = await searchAPI(query) isLoading.value = false }, 300)})</script>Dokumentation
Abschnitt betitelt „Dokumentation“Offizielle Vue Dokumentation:
- Computed Properties - Grundlagen
- Watchers - Watch & WatchEffect
API Referenz: