State

The introduction showed you a counter that worked, and promised to explain it. Here's the explanation. First, try the same counter with a plain variable:

<script setup>
let stamps = 0;

function addStamp() {
    stamps++;
    console.log(stamps);
}
</script>

<template>
    <p>Stamps: {{ stamps }}</p>
    <button @click="addStamp">Add a stamp</button>
</template>

Click the button three times, and the console shows:

1
2
3

So the variable does change, but the page still says Stamps: 0. Why? Vue renders the template: it makes the page's elements from it, with the values that the variables have at that moment. It renders the template again only when it knows that something the template uses has changed. A plain variable can't tell anyone that it has changed, so Vue never finds out, and the page stays as it was rendered the first time.

For values that change, Vue has ref():

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

const stamps = ref(0);

function addStamp() {
    stamps.value++;
}
</script>

<template>
    <p>Stamps: {{ stamps }}</p>
    <button @click="addStamp">Add a stamp</button>
</template>

Now each click adds a stamp, and the page shows it at once. What's new:

  • import { ref } from "vue"; takes the function ref from Vue, so that you can use it in this file.
  • ref(0) makes a ref, a small object that holds a value, here 0. In the script, the value is stamps.value, and that's what you change. In the template, it's still just stamps; the next exercise explains why.
  • When stamps.value changes, Vue knows it, and renders the template again with the new value. You don't change the page yourself, as you did with textContent in the JavaScript course. You change the data, and Vue changes the page.

The data of an app that can change, such as the number of stamps, is called its state. Values that Vue keeps track of like this are reactive: the page reacts when they change.

Typical mistake: no import line. The page stays empty, and the console says ReferenceError: ref is not defined.

Instructions

  1. Click Next, please a few times. The console shows the number going up, but the page doesn't. Make serving a ref, so that the page shows the new number after each click. (You can delete the console.log().)

  2. Add a button Start over after Next, please. Its handler, a function startOver(), sets the number back to 1.