A Button That Counts

So far, the data hasn't changed while the app was running. But in apps, it changes all the time: a customer adds an espresso to the order, and the number on the page goes up. Here's a button that does that:

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

const espressos = ref(0);

function addEspresso() {
    espressos.value++;
}
</script>

<template>
    <button @click="addEspresso">Add an espresso</button>
    <p>Espressos in your order: {{ espressos }}</p>
</template>

Three new things make it work:

  • import { ref } from "vue"; takes the function ref from Vue, so that the script can use it, just as main.js takes createApp.
  • ref(0) creates a ref, a value that Vue keeps an eye on, here starting at 0. In the script, the value is in espressos.value, so the function increases espressos.value. In the template, you write just {{ espressos }}, without .value.
  • @click="addEspresso" runs the function addEspresso on every click on the button, as addEventListener("click", addEspresso) did in the JavaScript course.

The most important part is what's missing: no line puts the new number on the page. When espressos.value changes, Vue updates every place in the template that shows espressos. In the JavaScript course, you had to change textContent yourself after each change, and it was easy to forget.

Why the ref and the .value? With a plain variable, let espressos = 0;, the number would change too, but Vue wouldn't know about it, and the page would keep showing 0. The lesson State and Events explains how refs work and shows much more about events. For now, it's enough to follow the pattern.

Instructions

  1. The order should show its price too. In <script setup>, create a second ref under espressos:

    const total = ref(0);

    At the end of the template, add a paragraph that shows it: <p>Total: €{{ total }}</p>. Click Run: the page shows Total: €0.

  2. An espresso costs €2, so each click should add 2 to the total. In addEspresso, add the line total.value += 2;. Click the button a few times: both numbers go up.