Vue methods vs watchers vs computed properties
By Flavio
Tagged: Vue.js
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.