Vue3 Watchers
In this section, we will introduce Vue3's watch property. We can use watch to respond to data changes.
The following example demonstrates a counter implemented using watch:
Example
<div id="app">
<p style="font-size:25px;">Counter: {{ counter }}</p>
<button @click="counter++" style="font-size:25px;">Click Me</button>
</div>
<script>
const app = {
data() {
return {
counter: 1
}
}
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('counter', function(nval, oval) {
alert('Counter value changed from: ' + oval + ' to ' + nval + '!');
});
</script>
The following example performs conversion between kilometers and meters:
Example
<div id="app">
Kilometers: <input type="text" v-model="kilometers" @focus="currentlyActiveField = 'kilometers'">
Meters: <input type="text" v-model="meters" @focus="currentlyActiveField = 'meters'">
</div>
<p id="info"></p>
<script>
const app = {
data() {
return {
kilometers: 0,
meters: 0
}
},
watch: {
kilometers(newValue, oldValue) {
// Check if the current input field is kilometers
if (this.currentlyActiveField === 'kilometers') {
this.kilometers = newValue;
this.meters = newValue * 1000;
}
},
meters(newValue, oldValue) {
// Check if the current input field is meters
if (this.currentlyActiveField === 'meters') {
this.kilometers = newValue / 1000;
this.meters = newValue;
}
}
}
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('kilometers', function(newValue, oldValue) {
// This callback will be invoked after vm.kilometers changes
document.getElementById("info").innerHTML = "Previous value: " + oldValue + ", New value: " + newValue;
});
</script>
Click the "Try it out" button to see the live example.
In the above code, we created two input fields with initial values of 0 for both kilometers and meters in the data property. The watch object creates two monitoring methods for the data object: kilometers and meters.
When we input data into the fields, the watch will listen for real-time changes and update the values accordingly. You can see the demonstration in the following video:
Using watch with Asynchronous Loading
For asynchronous data loading, Vue provides a more general method through the watch option to respond to data changes.
The following example uses the axios library, which will be introduced later.
Example
<!-- Since the ecosystem of AJAX libraries and general-purpose tools is quite rich, Vue core code does not duplicate -->
<!-- these functionalities to stay lean. This also allows you to freely choose the tools you are more familiar with. -->
<script src="https://cdn.staticfile.org/axios/0.27.2/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue/3.2.37/vue.global.min.js"></script>
<script>
const watchExampleVM = Vue.createApp({
data() {
return {
question: '',
answer: 'Questions should end with a question mark (?).'
}
},
watch: {
// This function will run whenever the question changes, compatible with both English and Chinese question marks
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
this.getAnswer();
}
}
},
methods: {
getAnswer() {
this.answer = 'Loading...';
axios
.get('/try/ajax/json_vuetest.php')
.then(response => {
this.answer = response.data.answer;
})
.catch(error => {
this.answer = 'Error! Unable to access the API. ' + error;
});
}
}
}).mount('#watch-example');
</script>