computed()
computed() derives a reactive value from other reactive sources. The result is cached and only recomputed when a dependency changes — the right tool for any value that’s a pure function of state.
Read-only + writable computed
EXAMPLE
<script setup>
import { ref, computed } from 'vue';
const first = ref('Ada');
const last = ref('Lovelace');
// 1) Read-only computed
const fullName = computed(() => `${first.value} ${last.value}`);
first.value = 'Grace';
console.log(fullName.value); // 'Grace Lovelace'
// 2) Writable computed — getter + setter
const displayName = computed({
get: () => fullName.value,
set: (val) => {
[first.value, last.value] = val.split(' ');
},
});
displayName.value = 'Linus Torvalds';
console.log(first.value, last.value); // Linus Torvalds
// 3) Filter / sort — cached
const users = ref([
{ id: 1, name: 'Ada', active: true },
{ id: 2, name: 'Bo', active: false },
{ id: 3, name: 'Cy', active: true },
]);
const query = ref('');
const activeUsers = computed(() => users.value.filter(u => u.active));
const filtered = computed(() =>
activeUsers.value.filter(u => u.name.toLowerCase().includes(query.value.toLowerCase()))
);
// 4) Pull from a store
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
const isAdmin = computed(() => userStore.user?.role === 'admin');
// 5) Computed inside a watcher — fine, just don't mutate in a computed
import { watch } from 'vue';
watch(filtered, (curr, prev) => {
console.log(`now ${curr.length} matches (was ${prev.length})`);
});
</script>
<template>
<p>Hello, {{ fullName }}!</p>
<input v-model="displayName" />
<input v-model="query" placeholder="Search active users" />
<ul>
<li v-for="u in filtered" :key="u.id">{{ u.name }}</li>
</ul>
</template>
<!-- 6) When to prefer computed vs method -->
<!-- Method: runs EVERY render — fine for simple things -->
<p>{{ fullName() }}</p> <!-- runs N times -->
<!-- Computed: runs once per dependency change — cached -->
<p>{{ fullName }}</p> <!-- runs 1 time -->
<!-- 7) Don't trigger side effects in a computed -->
<!-- BAD: -->
<!-- const total = computed(() => { sendAnalytics(); return rows.value.length; }); -->
<!-- Use watch() for side effects; computed() ONLY for derived data. -->
Why it matters
computed() is memoised + reactive. Reach for it any time you’d be tempted to call a method in your template — the framework caches it for free and you keep the template declarative.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
import { ref, computed } from 'vue';
const price = ref(100);
const withTax = computed(() => price.value * 1.1);
Try it Yourself »
Exercise
Derive a cached, dependency-tracked value.
const double =
(() => count.value * 2)
Starts with c.
Discussion
Loading…