Vue.js: Computed Properties

Last updated: 2026-10-20

Computed properties (computed) are special properties in Vue 3 that recalculate automatically from reactive data. Their core value is caching — they only recompute when a dependency changes; otherwise they return the last value. Understanding computed is the key to writing high-performance Vue apps.

Computed properties rest on three characteristics: automatic dependency tracking + cached results + reactivity. This lesson covers 5 usage patterns and 3 pitfalls.

Related Core:computed()

1. What You'll Learn


2. A Shopping Cart Total Performance Problem

(1) The Pain: Recalculating 100 Products on Every Click

Alice implemented the cart total in an e-commerce admin:

JS
// ❌ The broken version: using methods
function cartTotal(items) {
  console.log('Calculating...')  // prints on every call
  return items.reduce((sum, item) => sum + item.price * item.quantity, 0)
}
HTML
<template>
  <div>
    <p>Total: ${{ cartTotal(items) }}</p>
    <p>Tax: ${{ cartTotal(items) * 0.08 }}</p>
    <p>Grand Total: ${{ cartTotal(items) * 1.08 }}</p>
    <button @click="showDate = new Date()">Update Time</button>
  </div>
</template>

The performance is terrible:

The performance monitor reports:

"The cartTotal function is called 5,000 times per page load. 100 products × 5,000 = 500,000 per-item calculations. 3 seconds of jank."

(2) The Vue computed Solution: Cache + Dependency Tracking

JS
import { ref, computed } from 'vue'

const items = ref([
  { price: 100, quantity: 2 },
  { price: 50, quantity: 1 }
])

// ✅ computed: depends only on items, so it does not recompute while items is unchanged
const cartTotal = computed(() => {
  console.log('Calculating...')  // prints only when items changes
  return items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
})

// computed handles all 3 usages automatically: it calculates once
const tax = computed(() => cartTotal.value * 0.08)
const grandTotal = computed(() => cartTotal.value * 1.08)

(3) The Payoff

After switching to computed:


3. computed() Basics

(1) Standard Syntax

JS
import { ref, computed } from 'vue'

const count = ref(0)

// Basic computed property
const doubleCount = computed(() => {
  return count.value * 2
})

// Shorthand
const doubleCount = computed(() => count.value * 2)

// Usage
console.log(doubleCount.value)  // 0
count.value = 5
console.log(doubleCount.value)  // 10

(2) Using It in Templates

Inside the template, {{ doubleCount }} does not need .value (it unwraps automatically).

(3) 5 Key Characteristics

100%
graph TB
    subgraph Computed Core Characteristics
        A[Automatic dependency tracking]
        B[Cached results]
        C[Reactivity]
        D[Lazy evaluation]
        E[Chainable]
    end
    
    style A fill:#42b883,color:#fff
    style B fill:#42b883,color:#fff
    style C fill:#42b883,color:#fff
    style D fill:#42b883,color:#fff
    style E fill:#42b883,color:#fff
Characteristic Description
Automatic dependency tracking Detects the reactive data used inside the function body
Cached results Repeated access computes once while dependencies are unchanged
Reactive Recomputes automatically when a dependency changes
Lazy Nothing is computed until it is accessed (saves work)
Chainable A computed can depend on other computeds

▶ Example: Basic computed

▶ Try it Yourself

Output:

TEXT
Subtotal: $1099, Tax (8%): $87.92, Discount: -$50, Total: $1136.92.
Each click on + Add 1 Case adds $50 to the subtotal, so tax and total recompute automatically.
TEXT
Subtotal: $1099
Tax (8%): $87.92
Discount: -$50
Total: $1136.92

4. computed vs methods: 5 Key Differences

Dimension computed methods
Caching ✅ No recompute while dependencies are unchanged ❌ Recomputes on every call
Reactivity ✅ Tracks dependencies automatically ❌ No tracking (pass values in manually)
Template access {{ doubleCount }} {{ doubleCount() }}
Parameters ❌ Not supported ✅ Accepts any arguments
Best for Simple derived values Complex logic, event handling

(4) 5 Selection Scenarios

Scenario Use computed Use methods
Displaying a doubled number ✅ ❌
Calculating a cart total ✅ ❌
Handling button clicks ❌ ✅
Sending API requests ❌ ✅
Formatting a date (no dependencies) ❌ ✅
Filtering a list (depends on data) ✅ ❌
Form validation ❌ ✅

▶ Example: computed vs methods

▶ Try it Yourself

Output:

TEXT
Both lines display 200.
The console shows computed called once, but methods called three times — the computed result is cached and reused.
TEXT
Computed (1 call): 200 | 200 | 200
Methods (3 calls): 200 | 200 | 200

console: computed called
console: methods called
console: methods called
console: methods called

(1) 📊 5 Performance Comparison Scenarios

Scenario methods calls computed calls
Used once in the template 1 1
Used 3 times in the template 3 1
Used 10 times in the template 10 1
Parent re-renders but items is unchanged Called again No recompute
A dependency changes Called again Recomputes

(2) 📊 5 Common Mistakes

Mistake Symptom Fix
Replacing computed with methods Poor performance when used repeatedly Switch to computed
Passing parameters to computed Error computed takes no parameters — use methods
Setter writing to itself Infinite loop Have the setter update dependencies, never fullName.value = ...
Circular dependency A→B→A Deadlock Remove one of the dependencies
Complex logic inside computed Hard to debug Extract methods and call them from computed

5. getter/setter: Two-Way Computed Properties

(1) Getter Only by Default

JS
const firstName = ref('Alice')
const lastName = ref('Smith')

// Only a getter
const fullName = computed(() => `${firstName.value} ${lastName.value}`)

console.log(fullName.value)  // Alice Smith
// fullName.value = 'Bob Lee'  // ❌ warning: computed properties are read-only

(2) Full getter + setter

JS
const firstName = ref('Alice')
const lastName = ref('Smith')

const fullName = computed({
  // Read: join the parts
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  // Write: split them apart
  set(newValue) {
    const parts = newValue.split(' ')
    firstName.value = parts[0]
    lastName.value = parts[1] || ''
  }
})

// ✅ Now it is readable and writable
fullName.value = 'Bob Lee'
console.log(firstName.value)  // Bob
console.log(lastName.value)   // Lee

(3) Two-Way Binding in Templates

▶ Example: getter + setter

▶ Try it Yourself

Output:

TEXT
The input starts with Alice Smith, and the two lines read First: Alice / Last: Smith.
Typing Bob Lee rewrites them to First: Bob / Last: Lee through the setter.
TEXT
[ Alice Smith           ]
First: Alice
Last: Smith

6. Chaining Computed Properties

(1) Nested computed

JS
const items = ref([
  { price: 100, quantity: 2 },
  { price: 50, quantity: 3 }
])

// Layer 1: subtotal of list prices
const subtotal = computed(() =>
  items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
)

// Layer 2: tax (based on subtotal)
const tax = computed(() => subtotal.value * 0.08)

// Layer 3: discount (based on subtotal)
const discount = computed(() => subtotal.value > 200 ? 20 : 0)

// Layer 4: final total
const total = computed(() => subtotal.value + tax.value - discount.value)

console.log(total.value)  // 350 * 1.08 - 20 = 358

(2) How Chained computed Caching Works

100%
graph TB
    A[items change] --> B[subtotal recomputes]
    B --> C[tax recomputes]
    B --> D[discount recomputes]
    C --> E[total recomputes]
    D --> E
    
    style A fill:#42b883
    style B fill:#42b883
    style E fill:#42b883

Only the computeds on the dependency chain recompute; ones that are never used are skipped.


7. Putting It Together: E-commerce Cart Total

▶ Example: Chaining computed

▶ Try it Yourself

Output:

TEXT
Base score: 85, Bonus: 5, Total: 90, Grade: A.
Clicking +5 points raises the score to 90, so the bonus becomes 10 and the grade jumps to A+.
TEXT
Base score: 85
Bonus: 5
Total: 90
Grade: A

Related Core:computed()

❓ FAQ

Q computed or methods — which one should I use?
A Use computed whenever you can (caching + automatic tracking). Use methods only when: (1) you need parameters; (2) the value does not depend on reactive data; (3) it is an event handler (@click and so on).
Q Can computed take parameters?
A No. computed takes zero parameters. If you need parameters, use a method instead (getDouble(n) { return n * 2 }), or have computed return a function: computed(() => (n) => n * 2).
Q Can computed be accessed outside setup?
A Yes. computed returns a ref object, so you can pass it to other components or functions. To keep it reactive, treat computed as a "derived ref".
Q What is the difference between computed and watch?
A computed is a "derived value" (calculate a new value from data); watch is a "listener" (run a side effect when data changes). computed is for pure calculation; watch is for requests, setting state, and so on.
Q Why is computed faster than methods?
A Caching. methods runs the function on every call; computed runs only when a dependency changes. Three usages of computed in a template calculate once; methods calculates three times.
Q How do I write a setter without an infinite loop?
A Inside the setter, only update the computed's dependencies (refs) — never assign to the computed itself. For example, the setter for fullName should update firstName / lastName, not fullName.value = ....
Q Can computed be asynchronous?
A No. computed is synchronous. For async work use watch or watchEffect. If you need an "async computed property", combine data() { return { result: null } } with watch + onMounted.

📖 Summary


📝 Exercises

  1. Basic (⭐) Write a computed property wordCount that counts the words in a piece of text (split on spaces).

    Data: const text = ref('Hello Vue 3 from Alice') should output 4.

  2. Intermediate (⭐⭐) Write a cart total calculation with 3 computed properties:

    • subtotal: the sum of price × quantity across all items
    • discount: $10 off from $100, $30 off from $200
    • total: subtotal - discount
    • 3 items: iPhone $999 × 1, Case $50 × 2, Charger $30 × 1
  3. Challenge (⭐⭐⭐) Build a complete "cart total system":

    1. 5 products, each with name/price/quantity
    2. 4 computed properties: subtotal / tax (8%) / discount ($20 off from $200) / total
    3. A fullName computed using getter/setter, where the setter updates firstName/lastName from the input
    4. Test dependency tracking for all 5 computeds (which ones recompute when any product changes)
    5. Draw the computed dependency graph with mermaid
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏