🧠 1. Computed Properties
📘 What they are
Computed properties are reactive values that depend on other reactive data.
They are cached and automatically re-run only when their dependencies change.
✅ Example: Basic Computed Property
<template>
<div>
<input v-model="firstName" placeholder="First name">
<input v-model="lastName" placeholder="Last name">
<p>Full name: {{ fullName }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`
})
</script>
🧩 How it works:
firstNameandlastNameare reactive (ref).fullNameautomatically updates when either one changes.- Vue caches the result — the function won’t re-run unless dependencies change.
⚙️ Example: Getter + Setter
Computed properties can also have both getter and setter functions.
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
const parts = newValue.split(' ')
firstName.value = parts[0]
lastName.value = parts[1] || ''
}
})
</script>
Now, if you do:
fullName.value = 'Jane Smith'
→ both firstName and lastName will update.
👀 2. Watchers
📘 What they are
Watchers let you run a function when data changes.
Unlike computed properties (which are declarative), watchers are imperative — you decide what happens when something changes.
✅ Example: Basic Watch
<template>
<input v-model="count" type="number">
<p>Count: {{ count }}</p>
</template>
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`Count changed from ${oldVal} → ${newVal}`)
})
</script>
🧠 How it works:
watch()tracks changes tocount.- When
countchanges, the callback runs withnewValandoldVal.
⚙️ Example: Watching Multiple Sources
You can watch multiple values together:
watch([firstName, lastName], ([newFirst, newLast]) => {
console.log(`Name changed to ${newFirst} ${newLast}`)
})
⏳ Example: Deep & Immediate Watch
If you’re watching an object or array, use deep: true.
const user = ref({ name: 'Alice', age: 20 })
watch(user, (newVal) => {
console.log('User changed:', newVal)
}, { deep: true })
If you want the watcher to run immediately (on component mount), use:
watch(user, (newVal) => {
console.log('Initial + Changed value:', newVal)
}, { immediate: true })
⚖️ Computed vs Watch — When to Use Which
| Feature | Computed Property | Watcher |
|---|---|---|
| Purpose | Derive a new value from existing data | Perform side effects when data changes |
| Runs | Only when dependencies change | Every time watched data changes |
| Cached | ✅ Yes | ❌ No |
| Use case | Displaying derived data | Fetching API data, debouncing, logging, animations, etc. |
🧩 Example Comparison
✅ Using Computed (for derived state)
const price = ref(10)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
✅ Using Watch (for side effects)
watch(total, (newTotal) => {
console.log(`Total changed to $${newTotal}`)
})
