JavaScript frameworks have become a vital part of web development. This is due to their easily accessible features, including component architecture, state management, and routing. These help reduce the stress, effort, and time needed to build a web app from scratch.

Vue, one of these frameworks, offers many features to speed up development. The watch feature lets you monitor the values of variables and expressions during program execution.

What Are Watchers in Vue?

Vue watchers are functions that monitor changes in a reactive property and respond accordingly. Watchers let you react to events and data modification.

To use a watcher, import the watch function from the vue package in your script:

 <script setup>
import { watch } from 'vue';
</script>

You can now use the watch function to implement a watcher in your Vue component. Here’s a simple example:

 <template>
  <div>
    <p>{{ user }}</p>
    <button @click="changeName">Change Name</button>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

const user = ref('Chinedu');

const changeName = () => {
  user.value = 'Victor'; // Change the user's name
};

watch(user, (newUser, oldUser) => {
  alert(`User name changed from "${oldUser}" to "${newUser}"`);
});
</script>

This simple component uses the watch function to monitor the change in a user's name. The snippet's template section defines the component's HTML structure, which includes a p tag that displays the value of the user reactive variable.

The template also contains a button element, with a changeName function attached to a click event listener. When the user variable changes, Vue triggers the callback function. The callback function displays an alert: “User name changed from "Chinedu" to "Victor".”

Comparing Watchers With Computed Properties

It’s important to understand the difference between watchers and computed properties. Although they are both used as reactivity tools in Vue, you should use them for different purposes.

For example, you could calculate the sum of a father and son's age with watchers, like this:

 <template>
  <input type="text" placeholder="Father's Age" v-model="father">
  <input type="text" placeholder="Son's Age" v-model="son">
  <p>Total Age: {{ total }}</p>
</template>

<script setup>
import { ref, watch } from 'vue';

const father = ref();
const son = ref();
const total = ref();

watch(son, (newAge, oldAge) => {
  total.value = Number(father.value) + Number(newAge)
})

watch(father, (newAge, oldAge) => {
  total.value = Number(newAge) + Number(son.value)
})

</script>

This Vue component uses watchers to get the sum of the father's and son's ages. To do so, it creates a new reactive variable, total. You can create a reactive variable when you use Vue’s Composition API.

The snippet then employs two watch functions to watch the son's and father's ages. For each age, either father or son, the snippet sums up the new value with the age of the other. It then saves the result to the total reactive variable.

Consider the same scenario in the above snippet to one that uses computed properties:

 <template>
  <input type="text" placeholder="Father's Age" v-model="father">
  <input type="text" placeholder="Son's Age" v-model="son">
  <p>Total Age: {{ total }}</p>
</template>

<script setup>
import { ref , computed } from 'vue';

const father = ref();
const son = ref();

const total = computed(() => {
  return Number(father.value) + Number(son.value);
});

</script>

This snippet, compared to the former, is more concise and easier to read. The snippet gets the sum of the father and son's age and saves it in a computed ref (variable), total. The template section then displays the total variable using interpolation, a data binding technique in Vue.

Even if you can get the total of the two ages with watchers, it is better to do so with computed properties. Using watchers in this situation can lead to slower loading times and harder debugging simply because it involves more code.

Do not use watchers as a replacement for computed properties. Use watchers to monitor and react to data changes, and computed properties when you want to derive new data from existing reactive data.

The Immediate Option Available to Watchers in Vue

The immediate option is a configuration you can use when creating a watcher. This option determines whether the watcher should trigger its callback immediately after Vue has mounted the component.

Here's an example of a component using a watcher with the immediate option:

 <script setup>
import { ref, watch } from 'vue';

const count = ref(10);

watch(
  count,
  (newCount, oldCount) => {
    console.log(`Count changed from ${oldCount} to ${newCount}`);
  },
  { immediate: true }
);
</script>

In the snippet above, the watcher will execute its callback immediately upon component initialization and log “Count changed from undefined to 10” to the console. This shows that the initial variable was undefined before Vue injected the value of 10 to the count ref.

The immediate option can be handy in scenarios where you want to perform an initial action or initialization based on the current value of the watched property. For instance, when you need your app to fetch data from an API once Vue mounts a component.

The Deep Option Available in Vue Watchers

The deep option available when working with watchers in Vue enables deep observation of changes within nested objects or arrays. When set to true, the watcher can detect changes within nested properties.

Here's an example of a Vue component with the deep option:

 <script setup>
import { ref, watch } from 'vue';

const data = ref({ length: 42 });

watch(
  data,
  (newData, oldData) => {
    console.log(`Data changed"`);
  },
  { deep: true }
);

// This will trigger the watcher because it's a deep change
data.value.length = 43;
</script>

The snippet above initializes the data ref with an object containing a length property. The snippet sets the deep option to true. It then logs to the console that data has changed since the length property has changed to 43.

Without the deep option set to true, the watch function won't notice any changes to the object. However, Vue tracks all nested and deep changes without the deep option when you initialize the data variable as a reactive object:

 <script setup>
import { ref, watch } from 'vue';

const data = reactive({ length: 42 });

watch(
  data,
  (newData, oldData) => {
    console.log(`Data changed"`);
  }
);

// This will trigger the watcher because it changes a reactive object
data.length = 43;
</script>

The watch function in the above snippet will log to the console that the data changed because the data variable is a reactive object.

Build Better Apps With Vue Watchers

Vue’s watchers can help you achieve fine-grained reactivity in your applications. They control how you can observe changes in data properties and run custom logic in response.

Understanding when to use watchers, their differences from computed properties, and options like immediate and deep can significantly enhance your ability to build very responsive Vue applications.