Vue Tip: Use Eager Computed Without Lazy Evaluation
Michael Hoffmann
@mokkapps
Computed properties are evaluated lazily which means they are only evaluated when they are accessed.
Lazy Evaluation
You can try it yourself in the following StackBlitz playground:
The demo includes the following App.vue
component:
<script setup lang="ts">
import { computed, ref } from 'vue'
const count = ref(0)
const computedCounter = ref(0)
const showDoubleCount = ref(false)
const doubleCount = computed(() => {
computedCounter.value++
return count.value * 2
})
</script>
<template>
<div class="container">
<span>Count: {{ count }}</span>
<button @click="count++">Increment</button>
<span>computedCounter: {{ computedCounter }}</span>
<span v-if="showDoubleCount">Double Count: {{ doubleCount }}</span>
<button @click="showDoubleCount = !showDoubleCount">Show Double Count</button>
</div>
</template>
You could assume that computedCounter
is incremented by each click on the Increment
button as it is part of the doubleCount
computed property. But that is not the case.
If you click the Increment
button you can see that computedCounter
stays at 0
although counter
is correctly incremented by each click.
If you now click Show Double Count
button and click the Increment
button afterward, counter
and computedCounter
both increment.
So let's take a look at what is happening behind the scenes:
The callback function of the computed property only runs once the computed's value is being read (initially or after it was marked for an update because one of its dependencies changed). In our example, the computed property is initially not being read as the template reference is unavailable due to the v-if
directive.
This lazy evaluation often confuses developers as they expect their computed property to update (by putting a console.log
inside its callback or expecting an updated value in the Vue DevTools) if one of its dependencies changes.
computedEager Composable
The computedEager VueUse composable provides a eager computed property without lazy evaluation.
It's a good choice for simple operations that contain a rarely changing return value (in most cases a boolean).
If you liked this Vue tip, follow me on BlueSky to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter :