Computed Properties
A computed property is a reactive value derived from other reactive state via a function, created with Vue's computed() API. Unlike a plain method call in a template, a computed property's value is cached based on its reactive dependencies: it only recalculates when one of the reactive values it reads inside its getter actually changes, and repeated reads between those changes return the cached result instantly. This caching behavior is the key distinction between computed properties and methods, and it's what makes computed() the idiomatic tool for any derived value used in a template.
Cricket analogy: A computed property is like a match referee's cached net-run-rate figure that only updates when an actual delivery changes the score, instantly reused between overs, making computed() the idiomatic tool any broadcast graphic should use for a derived stat like NRR rather than recalculating it fresh every second.
Basic Usage and Caching
computed() accepts a getter function and returns a read-only ref-like object (again accessed via .value in script code, auto-unwrapped in templates). Internally, Vue tracks every reactive dependency accessed during the getter's execution and marks the computed value as "dirty" whenever any of those dependencies change; the getter only re-runs the next time the computed value is actually read after being marked dirty — this lazy, cached evaluation model avoids redundant recomputation, which matters a great deal for expensive derivations like filtering or sorting large lists.
Cricket analogy: computed() returning a read-only, ref-like object is like a stadium's official NRR display that fans can read (.value) but not scribble on — Vue marks it 'dirty' only when an actual delivery changes the score, recalculating lazily on the next glance, which saves effort for expensive calculations like a full tournament's net-run-rate table across many teams.
Writable Computed Properties
By default, computed() properties are read-only, and attempting to assign to their .value in script code (or bind them with v-model in a way that requires writing) will emit a runtime warning. For cases where you need a two-way derived binding — for example, splitting a full name into first/last name fields — you can pass an object with both a get() and a set() function to computed(), producing a writable computed property that can be used directly with v-model.
Cricket analogy: A default computed 'strike rate' display is read-only — you can't manually type in a new number, that would throw a warning — but for splitting a player's 'full name' into first/last name fields for the scorecard, you'd define both a get() (combine names) and a set() (split them back apart) so editors can update either field via v-model.
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('Ada')
const lastName = ref('Lovelace')
// Read-only computed: derived, cached, recalculates only when firstName/lastName change
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
// Writable computed: supports v-model by defining get and set
const fullNameEditable = computed({
get: () => `${firstName.value} ${lastName.value}`,
set: (newValue) => {
const [first, last] = newValue.split(' ')
firstName.value = first
lastName.value = last ?? ''
},
})
</script>
<template>
<p>{{ fullName }}</p>
<input v-model="fullNameEditable" />
</template>A method called in a template (e.g. {{ getFullName() }}) re-executes on every single re-render of the component, regardless of whether its inputs changed, because template re-renders re-evaluate every expression. A computed property with the same logic only re-executes when its tracked dependencies actually change — for anything beyond a trivial calculation, this is a meaningful performance difference.
Computed getters must be pure and synchronous — they should not have side effects (like mutating other state or making network requests) and should not depend on non-reactive values (like Date.now() or Math.random()) if you expect the cached value to ever update, since Vue has no way to know those values changed.
- computed() derives a cached, reactive value from a getter function that reads other reactive state.
- Computed values only recalculate when their tracked dependencies change — unlike methods, which rerun every render.
- computed() returns a ref-like object accessed via .value in script, auto-unwrapped in templates.
- By default computed properties are read-only; a get/set object makes them writable for v-model use.
- Computed getters must be pure, synchronous, and free of side effects to behave predictably.
- Use computed() for any derived value used in a template instead of calling a method directly.
Practice what you learned
1. What is the main behavioral difference between a computed property and a method called in a template?
2. How do you create a writable computed property?
3. What should computed getters avoid doing?
4. How is a computed property's value accessed in <script setup> JavaScript code?
5. Why might filtering a large array be better implemented as a computed property than a method call in the template?
Was this page helpful?
You May Also Like
reactive() and ref()
A deep dive into Vue 3's two core reactivity primitives — ref() for any value type and reactive() for objects — and when to use each.
Watchers Explained
How watch() and watchEffect() let you run side effects in response to reactive state changes, and how to choose between them.
Computed Caching and Performance
Explains how Vue's computed properties memoize their results based on reactive dependencies, and how to use that caching behavior deliberately to avoid wasteful recalculation in components.
The Composition API vs Options API
Compares Vue's two component authoring styles, explaining why the Composition API was introduced and when each approach makes sense in real projects.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics