[Medium] watch vs watchEffect
1. What are watch and watchEffect?
Was sind watch und watchEffect?
watch und watchEffect sind zwei APIs der Vue 3 Composition API zum Überwachen von Änderungen reaktiver Daten.
watch
Definition: Gibt explizit die zu überwachende Datenquelle an und führt eine Callback-Funktion aus, wenn sich die Daten ändern.
<script setup>
import { ref, watch } from 'vue';
const count = ref(0);
const message = ref('Hello');
// Einzelne Datenquelle überwachen
watch(count, (newValue, oldValue) => {
console.log(`count änderte sich von ${oldValue} zu ${newValue}`);
});
// Mehrere Datenquellen überwachen
watch([count, message], ([newCount, newMessage], [oldCount, oldMessage]) => {
console.log('count oder message hat sich geändert');
});
</script>
watchEffect
Definition: Verfolgt automatisch die reaktiven Daten, die in der Callback-Funktion verwendet werden, und führt sie automatisch aus, wenn sich diese Daten ändern.
<script setup>
import { ref, watchEffect } from 'vue';
const count = ref(0);
const message = ref('Hello');
// Verfolgt automatisch count und message
watchEffect(() => {
console.log(`count: ${count.value}, message: ${message.value}`);
// Wenn sich count oder message ändert, automatisch ausführen
});
</script>
2. watch vs watchEffect: Key Differences
Hauptunterschiede zwischen watch und watchEffect
1. Angabe der Datenquelle
watch: Gibt explizit die zu überwachenden Daten an
const count = ref(0);
const message = ref('Hello');
// Explizit count überwachen
watch(count, (newVal, oldVal) => {
console.log('count hat sich geändert');
});
// Explizit mehrere Daten überwachen
watch([count, message], ([newCount, newMessage]) => {
console.log('count oder message hat sich geändert');
});
watchEffect: Verfolgt automatisch verwendete Daten
const count = ref(0);
const message = ref('Hello');
// Verfolgt automatisch count und message (da sie im Callback verwendet werden)
watchEffect(() => {
console.log(count.value); // Verfolgt count automatisch
console.log(message.value); // Verfolgt message automatisch
});
2. Ausführungszeitpunkt
watch: Standardmäßig lazy (verzögert), führt nur bei Datenänderung aus
const count = ref(0);
watch(count, (newVal) => {
console.log('Ausgeführt'); // Nur wenn sich count ändert
});
count.value = 1; // Löst Ausführung aus
watchEffect: Sofortige Ausführung, dann Änderungen verfolgen
const count = ref(0);
watchEffect(() => {
console.log('Ausgeführt'); // Wird sofort einmal ausgeführt
console.log(count.value);
});
count.value = 1; // Erneute Ausführung
3. Zugriff auf alten Wert
watch: Kann auf den alten Wert zugreifen
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log(`Änderte sich von ${oldVal} zu ${newVal}`);
});
watchEffect: Kein Zugriff auf den alten Wert
const count = ref(0);
watchEffect(() => {
console.log(count.value); // Kann nur auf aktuellen Wert zugreifen
// Alter Wert nicht verfügbar
});
4. Überwachung stoppen
watch: Gibt eine Stopp-Funktion zurück
const count = ref(0);
const stopWatch = watch(count, (newVal) => {
console.log(newVal);
});
// Überwachung stoppen
stopWatch();
watchEffect: Gibt eine Stopp-Funktion zurück
const count = ref(0);
const stopEffect = watchEffect(() => {
console.log(count.value);
});
// Überwachung stoppen
stopEffect();
3. When to Use watch vs watchEffect?
Wann watch verwenden? Wann watchEffect?
Wann watch verwenden
-
Explizite Angabe der zu überwachenden Daten erforderlich
watch(userId, (newId) => {
fetchUser(newId);
}); -
Zugriff auf alten Wert erforderlich
watch(count, (newVal, oldVal) => {
console.log(`Änderte sich von ${oldVal} zu ${newVal}`);
}); -
Lazy-Ausführung erforderlich (nur bei Änderung)
watch(searchQuery, (newQuery) => {
if (newQuery.length > 2) {
search(newQuery);
}
}); -
Feinere Kontrolle erforderlich
watch(
() => user.value.id,
(newId) => {
fetchUser(newId);
},
{ immediate: true, deep: true }
);
Wann watchEffect verwenden
-
Automatische Verfolgung mehrerer zusammenhängender Daten
watchEffect(() => {
// Verfolgt automatisch alle verwendeten reaktiven Daten
if (user.value && permissions.value.includes('admin')) {
loadAdminData();
}
}); -
Alter Wert nicht benötigt
watchEffect(() => {
console.log(`Aktueller Zähler: ${count.value}`);
}); -
Sofortige Ausführung erforderlich
watchEffect(() => {
// Sofort ausführen, dann Änderungen verfolgen
updateChart(count.value, message.value);
});
4. Common Interview Questions
Häufige Interviewfragen
Frage 1: Grundlegende Unterschiede
Erklären Sie die Ausführungsreihenfolge und das Ergebnis des folgenden Codes.
const count = ref(0);
const message = ref('Hello');
// watch
watch(count, (newVal) => {
console.log('watch:', newVal);
});
// watchEffect
watchEffect(() => {
console.log('watchEffect:', count.value, message.value);
});
count.value = 1;
message.value = 'World';
Klicken Sie hier, um die Antwort zu sehen
const count = ref(0);
const message = ref('Hello');
// watch: lazy Ausführung, wird nicht sofort ausgeführt
watch(count, (newVal) => {
console.log('watch:', newVal);
});
// watchEffect: sofortige Ausführung
watchEffect(() => {
console.log('watchEffect:', count.value, message.value);
// Sofortige Ausgabe: watchEffect: 0 Hello
});
count.value = 1;
// Löst watch aus: watch: 1
// Löst watchEffect aus: watchEffect: 1 Hello
message.value = 'World';
// watch überwacht message nicht, wird nicht ausgeführt
// watchEffect überwacht message, Ausführung: watchEffect: 1 World
Ausgabereihenfolge:
watchEffect: 0 Hello(sofortige Ausführung)watch: 1(count geändert)watchEffect: 1 Hello(count geändert)watchEffect: 1 World(message geändert)
Wesentliche Unterschiede:
watchlazy Ausführung, nur bei Änderung der überwachten DatenwatchEffectsofortige Ausführung, verfolgt dann alle verwendeten Daten
Frage 2: Zugriff auf alten Wert
Erklären Sie, wie man bei Verwendung von watchEffect an den alten Wert gelangt.
Klicken Sie hier, um die Antwort zu sehen
Problem: watchEffect kann nicht direkt auf den alten Wert zugreifen
const count = ref(0);
watchEffect(() => {
console.log(count.value); // Kann nur auf aktuellen Wert zugreifen
// Alter Wert nicht verfügbar
});
Lösung 1: ref zum Speichern des alten Werts verwenden
const count = ref(0);
const prevCount = ref(0);
watchEffect(() => {
console.log(`Änderte sich von ${prevCount.value} zu ${count.value}`);
prevCount.value = count.value; // Alten Wert aktualisieren
});
Lösung 2: watch verwenden (wenn alter Wert benötigt)
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log(`Änderte sich von ${oldVal} zu ${newVal}`);
});
Empfehlung:
- Wenn der alte Wert benötigt wird, bevorzugt
watchverwenden watchEffecteignet sich für Szenarien ohne Bedarf an altem Wert
Frage 3: watch oder watchEffect wählen?
Erklären Sie, welches in den folgenden Szenarien verwendet werden sollte: watch oder watchEffect.
// Szenario 1: Benutzer-ID-Änderung überwachen, Benutzerdaten neu laden
const userId = ref(1);
// ?
// Szenario 2: Bei bestandener Formularvalidierung automatisch Absenden-Button aktivieren
const form = reactive({ username: '', password: '' });
const isValid = computed(() => form.username && form.password);
// ?
// Szenario 3: Suchbegriff überwachen, Suche ausführen (mit Debounce)
const searchQuery = ref('');
// ?
Klicken Sie hier, um die Antwort zu sehen
Szenario 1: Benutzer-ID überwachen
const userId = ref(1);
// ✅ watch verwenden: explizite Angabe der zu überwachenden Daten
watch(userId, (newId) => {
fetchUser(newId);
});
Szenario 2: Formularvalidierung
const form = reactive({ username: '', password: '' });
const isValid = computed(() => form.username && form.password);
// ✅ watchEffect verwenden: automatische Verfolgung zusammenhängender Daten
watchEffect(() => {
submitButton.disabled = !isValid.value;
});
Szenario 3: Suche (mit Debounce)
const searchQuery = ref('');
// ✅ watch verwenden: feinere Kontrolle erforderlich (Debounce)
let timeoutId;
watch(searchQuery, (newQuery) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
search(newQuery);
}, 300);
});
Auswahlprinzipien:
- Explizite Überwachungsdaten angeben →
watch - Automatische Verfolgung mehrerer zusammenhängender Daten →
watchEffect - Alter Wert oder feine Kontrolle benötigt →
watch - Sofortige Ausführung benötigt →
watchEffect
5. Best Practices
Beste Praktiken
Empfohlene Vorgehensweisen
// 1. watch verwenden, wenn explizite Überwachungsdaten angegeben werden
watch(userId, (newId) => {
fetchUser(newId);
});
// 2. watchEffect verwenden, wenn mehrere zusammenhängende Daten automatisch verfolgt werden
watchEffect(() => {
if (user.value && permissions.value.includes('admin')) {
loadAdminData();
}
});
// 3. watch verwenden, wenn alter Wert benötigt wird
watch(count, (newVal, oldVal) => {
console.log(`Änderte sich von ${oldVal} zu ${newVal}`);
});
// 4. Überwacher bereinigen nicht vergessen
onUnmounted(() => {
stopWatch();
stopEffect();
});
Zu vermeidende Praktiken
// 1. Keine asynchronen Operationen in watchEffect ohne Bereinigung
watchEffect(async () => {
const data = await fetchData(); // ❌ Kann zu Speicherlecks führen
// ...
});
// 2. watchEffect nicht übermäßig verwenden
// Wenn nur bestimmte Daten überwacht werden müssen, ist watch expliziter
watchEffect(() => {
console.log(count.value); // ⚠️ Wenn nur count überwacht werden muss, ist watch besser geeignet
});
// 3. Keine überwachten Daten in watchEffect ändern (mögliche Endlosschleife)
watchEffect(() => {
count.value++; // ❌ Kann Endlosschleife verursachen
});
6. Interview Summary
Interview-Zusammenfassung
Schnelle Merkhilfe
watch:
- Gibt explizit die zu überwachenden Daten an
- Lazy-Ausführung (Standard)
- Kann auf alten Wert zugreifen
- Geeignet für Szenarien mit feiner Kontrolle
watchEffect:
- Verfolgt automatisch verwendete Daten
- Sofortige Ausführung
- Kein Zugriff auf alten Wert
- Geeignet für automatische Verfolgung mehrerer zusammenhängender Daten
Auswahlprinzipien:
- Explizite Überwachung →
watch - Automatische Verfolgung →
watchEffect - Alter Wert benötigt →
watch - Sofortige Ausführung benötigt →
watchEffect
Beispielantwort für Interviews
F: Was ist der Unterschied zwischen watch und watchEffect?
"watch und watchEffect sind beide Vue 3 APIs zum Überwachen von Änderungen reaktiver Daten. Die Hauptunterschiede umfassen: 1) Datenquelle: watch erfordert die explizite Angabe der zu überwachenden Daten, watchEffect verfolgt automatisch die reaktiven Daten im Callback; 2) Ausführungszeitpunkt: watch ist standardmäßig lazy, führt nur bei Datenänderung aus, watchEffect führt sofort aus und verfolgt dann Änderungen; 3) Zugriff auf alten Wert: watch kann auf den alten Wert zugreifen, watchEffect nicht; 4) Anwendungsszenarien: watch eignet sich für explizite Datenüberwachung oder wenn der alte Wert benötigt wird, watchEffect eignet sich für die automatische Verfolgung mehrerer zusammenhängender Daten."
F: Wann sollte man watch verwenden? Wann watchEffect?
"watch verwenden bei: 1) Expliziter Angabe der zu überwachenden Daten; 2) Bedarf am alten Wert; 3) Lazy-Ausführung; 4) Feiner Kontrolle (wie immediate, deep Optionen). watchEffect verwenden bei: 1) Automatischer Verfolgung mehrerer zusammenhängender Daten; 2) Kein Bedarf am alten Wert; 3) Sofortiger Ausführung. Generell gilt: Wenn nur bestimmte Daten überwacht werden müssen, ist watch expliziter; wenn mehrere zusammenhängende Daten automatisch verfolgt werden sollen, ist watchEffect bequemer."