Computed and Watch
Introduction
Computed properties derive values from reactive state with caching—ideal for formatted text and filtered lists. Watchers run side effects when data changes—API calls, logging, syncing to localStorage. This chapter covers computed, watch, and watchEffect, and when to prefer each over template expressions or methods.
Prerequisites
computed Basics
Code explanation:
computedreturns a readonly ref by default- Re-runs only when
firstNameorlastNamechange - Template unwraps
fullNamelike a ref
computed vs Methods vs Template Logic
| Approach | Caches result | Use |
|---|---|---|
| Template expression | No | Trivial math |
| Method | No (runs each render) | Event handlers |
| computed | Yes | Derived lists, labels, flags |
Writable computed
Rare but useful—split get/set:
watch
Explicit source + side effect:
Watch options:
| Option | Meaning |
|---|---|
immediate: true | Run callback once on setup |
deep: true | Deep watch reactive object |
flush: 'post' | After DOM update |
Watch multiple sources:
watch([firstName, lastName], ([first, last]) => {
console.log(first, last);
});Watch a getter:
watch(
() => state.user.id,
(id) => { /* ... */ }
);watchEffect
Auto-tracks dependencies used inside:
<script setup lang="ts">
import { ref, watchEffect } from "vue";
const count = ref(0);
watchEffect(() => {
document.title = `Count: ${count.value}`;
});
</script>Cleanup on re-run or unmount:
watchEffect((onCleanup) => {
const timer = setInterval(() => {}, 1000);
onCleanup(() => clearInterval(timer));
});| watch | watchEffect | |
|---|---|---|
| Source | Explicit | Automatic |
| Old value | Available | No |
| Lazy | Default lazy | Runs immediately |
Use watch when you need old/new values or precise control; watchEffect for quick side effects.
When Not to Watch
Prefer computed for derived data—not watch copying state:
// Avoid
watch(a, (v) => { b.value = v * 2 });
// Prefer
const b = computed(() => a.value * 2);Use watch for async side effects (fetch, timers, localStorage).
localStorage Sync Example
Pinia persistence plugins scale this pattern—Pinia.
Practice Exercise
Add to todo filter example:
activeCountcomputed — number of undone todoswatchon filter —console.logfilter changes (dev only)- Replace template
visibleTodos()method withfilteredTodoscomputed
FAQ
computed vs watch for filtered list?
computed—pure derivation, cached.
watch immediate vs watchEffect?
Both run on start; watch needs immediate: true.
Deep watch performance?
Expensive on large objects—watch specific fields or use immutable updates.
Async in computed?
No—computed must be synchronous. Use watch + ref for async results.
Same as React useMemo/useEffect?
Rough analogy—computed ≈ memoized derive; watch ≈ effect on dependency.
Stop watch?
const stop = watch(source, callback);
stop();Useful in composables cleaned up on unmount.