How to watch deep objects in Vue
Watching deeply nested objects is essential for Vue applications that need to react to changes in complex data structures. As the creator of CoreUI with over 11 years of Vue development experience since 2014, I’ve implemented deep watchers in countless form validation and state management scenarios. The most effective solution is to use the watch function with the deep option to monitor all nested property changes. This approach ensures reactivity for complex objects with multiple levels of nesting.
Use the deep option in watch to monitor nested object changes in Vue 3.
<template>
<div>
<h2>User Profile</h2>
<input v-model='user.name' placeholder='Name' />
<input v-model='user.email' placeholder='Email' />
<h3>Address</h3>
<input v-model='user.address.street' placeholder='Street' />
<input v-model='user.address.city' placeholder='City' />
<input v-model='user.address.zip' placeholder='Zip' />
<p>Changes detected: {{ changeCount }}</p>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const user = ref({
name: 'John Doe',
email: '[email protected]',
address: {
street: '123 Main St',
city: 'New York',
zip: '10001'
}
})
const changeCount = ref(0)
// Watch with deep option
watch(
user,
(newValue, oldValue) => {
changeCount.value++
console.log('User object changed:', newValue)
// Save to API or localStorage
},
{ deep: true }
)
// Watch specific nested property
watch(
() => user.value.address.city,
(newCity, oldCity) => {
console.log(`City changed from ${oldCity} to ${newCity}`)
}
)
return { user, changeCount }
}
}
</script>
The watch function with { deep: true } monitors all nested properties recursively. Any change at any nesting level triggers the watcher. This is useful for forms, complex state objects, or configuration objects. For better performance, watch specific nested properties using a getter function when you only need to track certain fields. Deep watchers have a performance cost with very large objects, so use them judiciously.
Best Practice Note
This is the same deep watching pattern we use in CoreUI Vue components for complex form validation. For very large objects, consider watching specific paths instead of the entire object. Use immediate: true option to run the watcher on component mount. For tracking which specific property changed, you may need to implement custom deep comparison logic.



