Vue.js 2 Watchers
By Flavio Copes
Learn how Vue.js 2 watchers let you spy on a single piece of component state and run a function whenever that property value changes, with a clear example.
A watcher is a special Vue.js feature that allows you to spy on one property of the component state, and run a function when that property value changes.
Watchers are made for side effects: logging, calling an API, saving to localStorage. If all you need is a value derived from other values, use a computed property instead. Reach for a watcher when a change must trigger an action.
Here’s an example. We have a component that shows a name, and allows you to change it by clicking a button:
<template>
<div>
<p>My name is {{name}}</p>
<button @click="changeName()">Change my name!</button>
</div>
</template>
<script>
export default {
data() {
return {
name: 'Flavio'
}
},
methods: {
changeName: function() {
this.name = 'Flavius'
}
}
}
</script>
When the name changes we want to do something, like printing a console log.
We can do so by adding to the watch object a property named as the data property we want to watch over:
<script>
export default {
data() {
return {
name: 'Flavio'
}
},
methods: {
changeName: function() {
this.name = 'Flavius'
}
},
watch: {
name: function() {
console.log(this.name)
}
}
}
</script>
Click the button and the console prints Flavius.
The function assigned to watch.name can optionally accept 2 parameters. The first is the new property value. The second is the old property value:
<script>
export default {
/* ... */
watch: {
name: function(newValue, oldValue) {
console.log(newValue, oldValue)
}
}
}
</script>
Watchers cannot be looked up from a template as you can with computed properties.
Running the watcher immediately
By default a watcher only runs when the value changes. It does not run when the component is created with its initial value. This trips people up when they expect the watcher to fire on load.
If you need that, use the object form with immediate: true:
watch: {
name: {
handler: function(newValue, oldValue) {
console.log(newValue, oldValue)
},
immediate: true
}
}
Now the handler also runs once at creation, with the initial value as newValue and undefined as oldValue.
Watching objects
Another gotcha: if you watch an object, the watcher fires when the object is replaced, not when one of its nested properties changes. To catch nested changes, add deep: true:
watch: {
user: {
handler: function(newValue) {
console.log(newValue.name)
},
deep: true
}
}
Deep watching walks the whole object on every change, so keep it for small objects.
Want me to talk about your product? You can sponsor this site.