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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs