Vue methods vs watchers vs computed properties
By Flavio Copes
Vue.js gives you methods, watchers, and computed properties. Learn when to use each one in Vue 3, from reacting to DOM events to deriving cached values.
In a Vue 3 component you have three places to put logic: methods, computed properties, and watchers. Use methods to react to events, computed properties to derive values from your data, and watchers to run side effects when a property changes.
They overlap a bit, so let’s look at each one with an example. The modern default is Composition API with <script setup>. Options API still works the same way if you prefer it.
When to use methods
- To react on some event happening in the DOM
- To call a function when something happens in your component. You can call a method from computed properties or watchers.
A method is a function you call explicitly. Nothing runs until something calls it:
<script setup>
import { ref } from 'vue'
const count = ref(0)
function addOne() {
count.value = count.value + 1
}
</script>
In the template you wire it to an event:
<button @click="addOne">Add one</button>
When to use computed properties
- You need to compose new data from existing data sources
- You have a variable you use in your template that’s built from one or more data properties
- You want to reduce a complicated, nested property name to a more readable and easy to use one, yet update it when the original property changes
- You need to reference a value from the template. In this case, creating a computed property is the best thing because it’s cached.
- You need to listen to changes of more than one data property
A computed property is a value derived from other values:
<script setup>
import { computed, ref } from 'vue'
const firstName = ref('Flavio')
const lastName = ref('Copes')
const fullName = computed(() => {
return firstName.value + ' ' + lastName.value
})
</script>
In the template you use {{ fullName }} like any data property. Vue caches the result and only recomputes it when firstName or lastName change. A method called from the template runs again on every re-render instead. Details in Vue computed properties.
When to use watchers
- You want to listen when a data property changes, and perform some action
- You want to listen to a prop value change
- You only need to listen to one specific property (an Options API
watchentry watches a single property; with the Composition API,watchalso accepts an array of sources) - You want to watch a data property until it reaches some specific value and then do something
A watcher runs a function every time one property changes. It’s the right tool for side effects, like a network request:
<script setup>
import { ref, watch } from 'vue'
const query = ref('')
watch(query, (newValue) => {
fetch('/api/search?q=' + newValue)
})
</script>
More patterns (immediate, deep) live in Vue watchers.
The same with the Options API
If you use the Options API instead of <script setup>, the same ideas map to the methods, computed, and watch options. Mount the app with createApp, not new Vue:
import { createApp } from 'vue'
createApp({
data() {
return {
count: 0,
firstName: 'Flavio',
lastName: 'Copes',
query: ''
}
},
methods: {
addOne() {
this.count = this.count + 1
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
},
watch: {
query(newValue) {
fetch('/api/search?q=' + newValue)
}
}
}).mount('#app')
A common mistake
A computed property must return its value synchronously. If you put a fetch() call in a computed property, the template gets a Promise instead of the data you wanted.
When you need async work in response to a change, use a watcher. The watcher fires the request, and its callback stores the result in a data property the template can render.
Want me to talk about your product? You can sponsor this site.