In Vue.js, a computed property is a dynamically calculated property based on other reactive properties.
They allow us to calculate derived values reactively. That is, values that depend on other data, and that update automatically when that data changes.
For example
- Transform data: For example, formatting a date or filtering a list.
- Calculate derived values: For example, calculating the total of a shopping cart.
Computed properties are reactive, meaning they update automatically when their dependencies change.
Furthermore, they are cached, so they are only recalculated when their dependencies change. This makes them efficient for expensive or repetitive calculations.
The computed function receives a getter (a function that returns the calculated value) and returns a reactive reference.
Let’s see it with a simple example, like calculating the square of a number.
<template>
<div>
<p>Number: {{ number }}</p>
<p>Square: {{ square }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const number = ref(2);
// Computed property to calculate the square of the number
const square = computed(() => {
return number.value * number.value;
});
function increment() {
number.value++;
}
</script>
In this example,
squareis a computed property that depends onnumber- Every time
numberchanges,squareis automatically recalculated.
Computed properties with setter
By default, computed properties are read-only. That is, if you try to assign a value to a computed property, Vue.js will throw an error.
However, it is also possible to create computed properties with a setter (if necessary).
Let’s see it with an example, where we calculate the full name, from first name and last name.
<template>
<div>
<p>Full name: {{ fullName }}</p>
<input v-model="firstName" placeholder="First Name" />
<input v-model="lastName" placeholder="Last Name" />
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('Juan');
const lastName = ref('Pérez');
// Computed property with getter and setter
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`;
},
set(value) {
const [newFirstName, newLastName] = value.split(' ');
firstName.value = newFirstName;
lastName.value = newLastName;
},
});
</script>
In this example,
fullNameis a computed property with a getter and a setter- The
getterreturns the full name - The
settersplits the value into first name and last name
Practical examples
Filter a list
Suppose we have a list of tasks and we want to filter the completed tasks.
<template>
<div>
<h2>Completed Tasks</h2>
<ul>
<li v-for="task in completedTasks" :key="task.id">
{{ task.text }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const tasks = ref([
{ id: 1, text: 'Learn Vue.js', completed: true },
{ id: 2, text: 'Go shopping', completed: false },
{ id: 3, text: 'Write an article', completed: true },
]);
// Computed property to filter the completed tasks
const completedTasks = computed(() => {
return tasks.value.filter(task => task.completed);
});
</script>
In this example, completedTasks is a computed property that filters completed tasks. If tasks changes, completedTasks is automatically recalculated.
Calculate the total of a shopping cart
Suppose we have a shopping cart and we want to calculate the total.
<template>
<div>
<h2>Shopping Cart</h2>
<ul>
<li v-for="product in cart" :key="product.id">
{{ product.name }} - ${{ product.price }}
</li>
</ul>
<p>Total: ${{ total }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const cart = ref([
{ id: 1, name: 'T-shirt', price: 20 },
{ id: 2, name: 'Pants', price: 40 },
{ id: 3, name: 'Shoes', price: 60 },
]);
// Computed property to calculate the total of the cart
const total = computed(() => {
return cart.value.reduce((sum, product) => sum + product.price, 0);
});
</script>
In this example, total is a computed property that calculates the total of the shopping cart. If cart changes, total is automatically recalculated.
