Vue 3 is the up and coming version of Vue front end framework.
It builds on the popularity and ease of use of Vue 2.
In this article, we’ll look at Vue computed properties and watchers.
Computed Properties
We can add computed properties to derive some from an existing property.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<input v-model="message" />
<p>{{reversedMessage}}</p>
</div>
<script>
const vm = Vue.createApp({
data() {
return {
message: ""
};
},
computed: {
reversedMessage() {
return this.message
.split("")
.reverse()
.join("");
}
}
}).mount("#app");
</script>
</body>
</html>
We added the message
property to the object we return in data
.
Then we added the computed
property to the object we passed into createApp
.
Methods are inside it getters, so we return things derived from other properties.
The method must be synchronous.
Now when we type in something to the input, we’ll see the reversed version displayed below it.
Computed Caching vs Methods
We can achieve the same result by running a method to reverse the string.
But it wouldn’t be cached based on their dependency if we use a regular method to return derived data.
Computed properties are cached based on the original reactive dependencies.
As long as this.message
stays the same, reversedMessage
won’t be run.
However, if we have dependencies that aren’t reactive in our computed property, then the method won’t run.
In this case, we’ve to use methods to make them update.
So something like:
computed: {
now() {
return Date.now()
}
}
won’t update.
Computed Setter
We can have setters in our computed properties.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<input v-model="firstName" placeholder="first name" />
<input v-model="lastName" placeholder="last name" />
<p>{{fullName}}</p>
</div>
<script>
const vm = Vue.createApp({
data() {
return {
firstName: "",
lastName: ""
};
},
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(newValue) {
const names = newValue.split(" ");
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
}).mount("#app");
</script>
</body>
</html>
We have the firstName
and lastName
properties in the object we return with data
.
Then we can create the getter for the fullName
property by returning the 2 properties combined into one string.
The setter would be the set
method which takes the newValue
and then split it back into its parts.
We set the this.firstName
and this.lastName
based on the combined string we have returned from get
.
When this.firstName
and this.lastName
change then get
is run.
If get
is run, then set
is run.
Watchers
Computed properties work for most cases, but sometimes we need watchers to provide us with a more generic way to watch for data changes.
For example, we can use it by writing:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<input v-model="name" />
<p>{{data}}</p>
</div>
<script>
const vm = Vue.createApp({
data() {
return {
name: "",
data: {}
};
},
watch: {
name(newName, oldName) {
if (oldName !== newName) {
this.getData(newName);
}
}
},
methods: {
getData(newName) {
fetch(`https://api.agify.io/?name=${newName}`)
.then(res => res.json())
.then(res => {
this.data = res;
});
}
}
}).mount("#app");
</script>
</body>
</html>
We have a getData
method which takes a newName
parameter and get some data from an API.
And then we have our watch
property, which has an object with watchers.
The name of the method would match the name of the instance property name.
A watcher takes an old value and a new value as the parameter.
And we can run what we want inside it.
The code we run is async so we got to use a watcher instead of computed properties.
Conclusion
Computed properties and watchers let us watch for reactive data changes and let us run code when they change.