Deriving State with Caching
Computed properties are used to generate values that depend on other reactive data. Unlike standard methods, they implement a caching mechanism: the value is recalculated only when its specific dependencies change. This optimization makes them superior for handling complex logic directly within templates.
Options API Example
Placing too much logic in a template can make it hard to maintain. For example, inverting a string or formatting text directly in the HTML is discouraged. The following example demonstrates how to move this logic into a computed property.
<div id="app">
<p>Original input: {{ rawInput }}</p>
<p>Formatted output: {{ formattedInput }}</p>
</div>
<script>
const app = {
data() {
return {
rawInput: 'Vue.js'
}
},
computed: {
formattedInput() {
// Returns the input in uppercase
return this.rawInput.toUpperCase();
}
}
}
Vue.createApp(app).mount('#app')
</script>
Composition API Usage
In the Composition API, the computed function is imported from 'vue'. It accepts a getter function and returns a read-only reactive reference. The example below calculates the total cost based on a base price and tax rate.
<template>
<div>
<p>Base Price: ${{ state.price }}</p>
<p>Tax Rate: {{ state.tax }}%</p>
<p>Total Cost: ${{ totalCost }}</p>
<button @click="updatePrice">Increase Price</button>
</div>
</template>
<script>
import { reactive, computed } from 'vue';
export default {
setup() {
const state = reactive({
price: 100,
tax: 20
});
// Computed property derived from state.price and state.tax
const totalCost = computed(() => {
const amount = state.price * (1 + state.tax / 100);
return amount.toFixed(2);
});
const updatePrice = () => {
state.price += 50;
};
return {
state,
totalCost,
updatePrice
};
}
};
</script>
Comparison with Methods
It is possible to use a method to achieve the same result as a computed property. However, methods are re-evaluated every time the component re-renders, regardless of whether the data it relies on has changed. Computed properties are cached based on their dependencies, making them more performant for expensive operations.
// Method approach (called on every render)
methods: {
calculateTotal() {
return this.price * 1.2;
}
}
Writable Computed Properties
By default, computed properties are read-only (getter-only). You can, however, define a setter to allow custom logic when assigning a new value to the computed property. This enables two-way binding for derived data.
const app = {
data() {
return {
firstName: 'Jane',
lastName: 'Doe'
}
},
computed: {
fullName: {
// Getter
get() {
return this.firstName + ' ' + this.lastName;
},
// Setter
set(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
}
const vm = Vue.createApp(app).mount('#app');
// Running the setter updates the underlying data
vm.fullName = 'Alice Smith';
console.log(vm.firstName); // "Alice"
console.log(vm.lastName); // "Smith"