Vue JS - Differences between Computed and Watch

Vue JS - Differences between Computed and Watch

When I started to code in Vue and had to react to changes, I always asked myself the same question: computed or watch? 🤔️. The both seem to do the same, right? However, a computed property may be better than a watcher in some cases or vice versa.

Computed

We can think of a computed property as a normal property, but with the difference that Vue automatically evaluates its value every time one of its dependencies is changed. For instance:

computed: {
  total() {
    return this.price * this.quantity;
  }
}

The total property will be calculated every time the price or the quantity changes.

Watch

A watcher is basically a function that Vue automatically executes when the watched property changes. If we take the above example, we could do it as follows:

watch: {
  quantity(val) {
    this.total = this.price * val;
  },
  price(val) {
    this.total = this.quantity * val;
  }
}

This works, but it's a lot of code. We would have to add a third watcher if the total property also depended on the tax. This is the main reason why it's a better idea to use a computed property instead.

While computed properties are more appropriate in most cases, watchers are more powerful and allow us to perform complex operations such as HTTP calls or execute some asynchronous logic that wouldn't be possible with a computed property.

Suppose we want to get the movies in which an actor appears. We could do it in the following way:

export default {
  data() {
    return {
      actorId: null,
      movies: [],
    };
  },
  methods: {
    getMovies() {
      // http request
      axios.get(`movies/actor/${this.actorId}`)
      .then(resp => {
        this.movies = resp.data;
      });
    }
  },
  watch: {
    actorId(val) {
      if(val) this.getMovies();
    }
  }
}

Another use case for a watcher is when we need to watch a data property until it reaches a specific value, and only then do something. For instance:

watch: {
  quantity(val) {
    if (val > this.stock) {
      this.error = true;
      this.errorMessage = `We only have ${this.stock} units`;
    }
  },
}

Conclusion

Computed properties and watchers have different use cases. It would be a better idea to use a computed property whenever we need to calculate a value based on other properties, considering that Vue will reevaluate the property every time any of its dependencies is changed and we will not need a custom watcher for each dependency. But a watcher would be better if we need to do something more generic than just get a value, such as HTTP calls, store data in local storage, set a timer, or whatever we couldn't do with computed properties.