JAVASCRIPT
Implement Deep Watchers for Nested Data Changes in Vue 3
Learn how to use deep watchers in Vue 3's Composition API to react to changes within nested properties of reactive objects, ensuring comprehensive state observation.
<template>
<div>
<p>User Name: {{ user.name }}</p>
<p>User Address City: {{ user.address.city }}</p>
<p>Messages: {{ messages.length }}</p>
<button @click="changeUserName">Change Name</button>
<button @click="changeUserCity">Change City</button>
<button @click="addMessage">Add Message</button>
</div>
</template>
<script setup>
import { reactive, ref, watch } from 'vue';
const user = reactive({
name: 'Alice',
age: 30,
address: {
street: '123 Vue St',
city: 'Vueville',
zip: '12345'
}
});
const messages = ref(['Hello', 'World']);
// Watch a reactive object deeply
watch(
user,
(newValue, oldValue) => {
console.log('User (deep watch) changed!');
console.log('New User:', newValue);
console.log('Old User:', oldValue); // Note: oldValue for deep watches is the same object as newValue in most cases, requiring a clone if you need a true snapshot.
},
{ deep: true }
);
// Watch a ref array deeply (also implicitly deep for refs holding objects)
watch(
messages,
(newValue, oldValue) => {
console.log('Messages (deep watch) changed!');
console.log('New Messages:', newValue);
console.log('Old Messages:', oldValue);
},
{ deep: true }
);
const changeUserName = () => {
user.name = 'Bob'; // Triggers deep watch
};
const changeUserCity = () => {
user.address.city = 'Nuxt City'; // Triggers deep watch due to deep: true
};
const addMessage = () => {
messages.value.push('New message ' + (messages.value.length + 1)); // Triggers deep watch
};
// Example: Watch a specific nested property
watch(
() => user.address.city,
(newCity, oldCity) => {
console.log(`User's city changed from ${oldCity} to ${newCity}`);
}
);
</script>
How it works: This snippet demonstrates how to use 'deep' watchers in Vue 3's Composition API to react to changes within nested properties of reactive objects or arrays. When you use `watch()` with `deep: true` in its options object, Vue will traverse all nested properties of the watched source. This is essential when you need to observe changes not just to the top-level property but also to any of its inner values. For `reactive` objects, `deep: true` is often necessary to catch changes in nested data. For `ref`s that hold objects or arrays, `deep: true` will also monitor their content. It's important to note that deep watching can be more performant-intensive, so it should be used judiciously.