Create Vue 3 Apps with the Composition API — Watch and Watch Effect

John Au-Yeung - Jan 19 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Vue 3 comes with the Composition API built-in.

It lets us extract logic easily an not have to worry about the value of this in our code.

It also works better with TypeScript because the value of this no longer has to be typed.

In this article, we’ll look at how to create Vue 3 apps with the Composition API.

watch

The watch function in the Vue 3 composition API is the same as Vue 2’s this.$watch method or the watch option.

Therefore, we can use it to watch for changes in reactive properties.

For instance, we can write:

<template>
  <div>
    <button @click="increment">increment</button>
    {{ state.count }}
  </div>
</template>

<script>
import { reactive, watch } from "vue";
export default {
  name: "App",
  setup() {
    const state = reactive({ count: 0 });

    const increment = () => {
      state.count++;
    };
    watch(
      () => state.count,
      (count, prevCount) => {
        console.log(count, prevCount);
      }
    );

    return {
      state,
      increment,
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

We watch a getter function in the 2nd argument.

And we get the current and previous value in the first and 2nd parameter of the function we pass into watch as the 2nd argument.

Now when we click on the increment button, we see state.count increase.

If we have a primitive valued reactive property, we can pass it straight into the first argument of watch :

<template>
  <div>
    <button @click="increment">increment</button>
    {{ count }}
  </div>
</template>

<script>
import { ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    const count = ref(0);
    const increment = () => {
      count.value++;
    };
    watch(count, (count, prevCount) => {
      console.log(count, prevCount);
    });

    return {
      count,
      increment,
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

And we get the same values we for count and prevCount when we click on the increment button.

Watching Multiple Sources

We can also watch multiple refs.

For instance, we can write:

<template>
  <div>
    <button @click="increment">increment</button>
    {{ foo }}
    {{ bar }}
  </div>
</template>

<script>
import { ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    const foo = ref(0);
    const bar = ref(0);
    const increment = () => {
      foo.value++;
      bar.value++;
    };
    watch([foo, bar], ([foo, bar], [prevFoo, prevBar]) => {
      console.log([foo, bar], [prevFoo, prevBar]);
    });

    return {
      foo,
      bar,
      increment,
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

We pass in the foo and bar refs into the array.

Then we get the current and previous values from the arrays in the parameters of the function in the 2nd argument.

We can also pass in the onInvalidate function into the 3rd argument.

And other behaviors are also shared with watchEffect .

Conclusion

We can watch reactive properties with Vue 3’s composition API watchers.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .