SyntaxStudy
Sign Up
Vue.js Computed Properties Basics
Vue.js Beginner 1 min read

Computed Properties Basics

Computed properties derive a value from reactive state. Unlike plain methods, they are cached based on their reactive dependencies — they only re-evaluate when one of their dependencies changes, making them highly efficient for expensive derivations. Accessing a computed property multiple times within the same render cycle returns the cached value without re-running the getter. You create a computed property by calling `computed(() => expression)`, which returns a readonly `ref`-like object whose `.value` holds the derived value. Inside templates the auto-unwrapping means you write `{{ fullName }}` rather than `{{ fullName.value }}`. Any reactive values accessed inside the getter — refs, reactive properties, other computeds — are automatically tracked as dependencies. Keep computed getters free of side effects. They should be pure functions: no mutation of other state, no async operations, no direct DOM access. If you need a side effect triggered by a state change, use `watch` instead. Trying to mutate a computed value throws a runtime warning — if you need a writable computed, define both `get` and `set` handlers.
Example
<script setup>
import { ref, computed } from 'vue';

const firstName = ref('Jane');
const lastName  = ref('Doe');
const cart      = ref([
  { name: 'Widget', price: 9.99,  qty: 2 },
  { name: 'Gadget', price: 24.99, qty: 1 }
]);

// ── Read-only computed ─────────────────────────
const fullName = computed(() => `${firstName.value} ${lastName.value}`);

const cartTotal = computed(() =>
  cart.value.reduce((sum, item) => sum + item.price * item.qty, 0)
);

const cartSummary = computed(() =>
  `${cart.value.length} item(s) — $${cartTotal.value.toFixed(2)}`
);

// ── Writable computed ─────────────────────────
const fullNameRW = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (val) => {
    const [first, ...rest] = val.split(' ');
    firstName.value = first;
    lastName.value  = rest.join(' ');
  }
});

// Setting fullNameRW updates both refs:
fullNameRW.value = 'John Smith';
</script>

<template>
  <p>{{ fullName }}</p>
  <p>{{ cartSummary }}</p>
</template>