100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

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.

Performance & ProductionIntermediate9 min readJul 9, 2026
Analogies

Computed Caching and Performance

A computed property in Vue is not just a convenient way to derive a value from other reactive state — it is a memoized, lazily-evaluated value backed by a dependency tracker. When you read a computed property, Vue checks whether any of the reactive sources it touched during its last evaluation have changed. If none have, it returns the cached value instantly without re-running the getter function. This is fundamentally different from calling a plain function in your template, which re-executes on every single render regardless of whether its inputs changed. Understanding this distinction is one of the highest-leverage performance skills in Vue development, because misusing computed properties (or using methods where computed properties belong) is one of the most common sources of unnecessary re-computation in real applications.

🏏

Cricket analogy: A computed property is like a scoreboard operator who only updates the run rate display when a run is actually scored, instantly showing the same cached number between deliveries, whereas a plain method is like an announcer who recalculates the run rate out loud after every single ball regardless of whether the score changed.

How dependency tracking drives the cache

When a computed getter runs, Vue's reactivity system records every reactive property it reads — refs, reactive object properties, other computed properties — as a dependency. The computed value is then marked dirty only when one of those exact dependencies is mutated. If your getter reads cart.items but never reads cart.discountCode, changing the discount code will not invalidate the cache, because that property was never tracked as a dependency in the first place. This fine-grained tracking, not a naive 'recompute on any state change' model, is what makes computed properties efficient even in components with large amounts of unrelated reactive state.

🏏

Cricket analogy: If a computed 'run rate' getter only reads the overs bowled and runs scored, changing the weather forecast display elsewhere on the broadcast won't invalidate the cached run rate, because Vue only tracked the specific properties actually read during the getter — like a scorer who ignores unrelated broadcast graphics.

Computed vs. method calls in templates

It is tempting to reach for a plain method when a template needs a derived value, especially since the syntax {{ formatPrice() }} looks almost identical to {{ formattedPrice }}. But a method invoked in a template re-runs on every re-render of the component, no matter the cause, while a computed property only re-runs when its tracked dependencies actually change. For cheap, trivial transforms the difference is negligible, but for anything involving array filtering, sorting, aggregation, or expensive string formatting across large lists, the gap becomes significant, especially inside components that re-render frequently due to unrelated prop or state changes.

🏏

Cricket analogy: Calling formatScore() as a method in the template is like asking the scorer to recalculate the entire tournament's net run rate from scratch after every single ball bowled anywhere in the stadium, even balls that don't involve this match, whereas a computed property only recalculates when this specific match's runs actually change.

vue
<script setup>
import { ref, computed } from 'vue'

const orders = ref([
  { id: 1, total: 42.5, status: 'paid' },
  { id: 2, total: 18.0, status: 'pending' },
  { id: 3, total: 96.2, status: 'paid' },
])

// Cached: only recomputes when `orders` changes.
const paidTotal = computed(() => {
  console.log('recalculating paidTotal')
  return orders.value
    .filter((order) => order.status === 'paid')
    .reduce((sum, order) => sum + order.total, 0)
})

// Not cached: re-runs on every render, even ones triggered
// by unrelated state elsewhere in the component.
function paidTotalMethod() {
  console.log('recalculating via method')
  return orders.value
    .filter((order) => order.status === 'paid')
    .reduce((sum, order) => sum + order.total, 0)
}
</script>

<template>
  <p>Computed: {{ paidTotal }}</p>
  <p>Method: {{ paidTotalMethod() }}</p>
</template>

Vue's caching applies to reads, not to the number of times a computed property is used in the template. You can reference the same computed property ten times across a component and the getter still only runs once per invalidation — the other nine reads are served from cache. This extends to chained computed properties too: each depends only on what it actually reads, so a change deep in the source state invalidates only the computed properties that depend on the affected path, propagating no further than necessary.

A common pitfall is writing a computed getter that reads from a non-reactive source, such as Date.now(), Math.random(), or a value pulled from localStorage outside of Vue's reactivity. Since these are not tracked dependencies, the computed property will cache its very first result forever and never update, which looks like a bug in the computed system but is actually a violation of its core assumption: getters must be pure functions of reactive state.

  • Computed properties cache their return value and only recompute when one of their tracked reactive dependencies changes.
  • Methods called in templates re-run on every render, regardless of whether their underlying data changed.
  • Dependency tracking is fine-grained: only reading a reactive property during evaluation registers it as a dependency.
  • Chained computed properties each maintain their own cache, so invalidation only propagates as far as necessary.
  • Computed getters must be pure — reading non-reactive sources like Date.now() breaks caching because Vue never sees a reason to invalidate.
  • Prefer computed properties over template methods for any non-trivial derived value, especially filtering, sorting, or aggregation over larger collections.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#VueJsStudyNotes#WebDevelopment#ComputedCachingAndPerformance#Computed#Caching#Performance#Dependency#StudyNotes#SkillVeris