Computed Values

Some values on a page aren't data of their own: they're worked out from other data. The total of an order comes from the prices of what's in it, and when the order changes, the total has to change too. For values like that, Vue has computed values:

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

const cups = ref(2);
const price = computed(() => cups.value * 3);
</script>

<template>
    <p>{{ cups }} cups of coffee cost €{{ price }}.</p>
    <button @click="cups++">One more</button>
</template>

The page shows 2 cups of coffee cost €6., and after a click, 3 cups of coffee cost €9. You give computed() a function that works out the value and returns it. Vue runs the function and remembers the result. When a ref that the function reads changes, here cups, Vue runs it again and updates the page. You never set price yourself.

A computed value is used like a ref. In the template, you write its name: {{ price }}. In the script, you add .value, also inside another computed value:

const withTip = computed(() => price.value + 1);

Like ref, computed comes from Vue, so it has to be in the import line: import { computed, ref } from "vue"; (this course lists the names in alphabetical order). Without it, the page stays empty, and the console shows ReferenceError: computed is not defined.

The function can be as long as it needs to be, with loops and conditions, as long as it returns the value at the end. And it's only for working the value out: a computed value can't be changed. price.value = 10; changes nothing, and the console shows [Vue warn]: Write operation failed: computed value is readonly. For a different price, change what it's made from, cups.

In this exercise, the café's order is an array of items with a count. When an item is already in the order, addToOrder() adds 1 to its count; otherwise, it puts the item in with count: 1.

Typical mistakes:

  • Forgetting .value in the script: total >= 10 compares the computed value itself, not the number in it, and it's never true.
  • Forgetting return: the function then returns nothing, and the page shows nothing in its place.

Instructions

  1. Create a computed value total, the price of the whole order: the sum of price * count of its items. Show it in the paragraph with the class total instead of the 0, as in Total: €7. Try adding a few items.

  2. Customers whose order costs at least €10 get a cookie. Create a computed value freeCookie that's true when total is at least 10. When it is, show a paragraph with the class gift and the text A cookie on the house! under the total.