Students make a Vue app, predict that the page follows the data with no textContent, match the parts of the app, find a plain variable Vue does not watch, add a button and new data, and make a two-value counter.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min
Read the unit primer first. A Vue app has two halves. The page is ordinary HTML inside <div id="app">, with {{ name }} wherever a value should appear. The setup function makes the data with ref(...) and returns the names the page may use. createApp({ setup() { … } }).mount("#app") joins them. When a ref changes, Vue redraws the parts of the page that show it: students never write textContent.
vue.js sits beside the page in the playground (it is served from this site). On a real site you would use Vue's file from vuejs.org or a build tool; teacher notes later in the course say more. The console shows one line about a development build: that is the version with friendlier warnings, chosen on purpose.
@click="score++" is a recipe in this lesson (events are lesson 3). The planted bug is a plain let variable: the click changes it but Vue is not watching, so the page never updates and there is no error. That is the most important idea in the course: Vue only keeps up with data it watches.
Students forget one of the three edits (ref, return, {{ }}) and the value does not show. Ask them to point to all three for each piece of data before you look at the code.
| What you will see | A question to ask | The fix |
|---|---|---|
| The page shows {{ score }} as text. | Is the vue.js line there, and does the app mount on #app? | Load vue.js before the script, and keep the {{ }} inside the div with id app. |
| A value is blank and the console warns it was accessed but is not defined. | Is its name in the return? | Add it: return { title, score, team }; |
| Clicks do nothing and there is no error. | Was the data made with ref? | const score = ref(0); a plain let is not watched. |
One possible solution for each task. Other correct programs are fine.
<div id="app">
<h1>{{ title }}</h1>
<p>Score: {{ score }}</p>
<button @click="score++">Add a point</button>
<button @click="score--">Take a point</button>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const title = ref("Quiz night");
const score = ref(0);
return { title, score };
}
}).mount("#app");
</script>
<div id="app">
<h1>{{ title }}</h1>
<p>Team: {{ team }}</p>
<p>Score: {{ score }}</p>
<button @click="score++">Add a point</button>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const title = ref("Quiz night");
const team = ref("Owls");
const score = ref(0);
return { title, team, score };
}
}).mount("#app");
</script>
<div id="app">
<h1>Space game</h1>
<p>Lives: {{ lives }}</p>
<p>Level: {{ level }}</p>
<button @click="lives--">Lose a life</button>
<button @click="level++">Next level</button>
</div>
<script src="vue.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const lives = ref(3);
const level = ref(1);
return { lives, level };
}
}).mount("#app");
</script>
Stretch: Show the score twice on the page (in the title and a paragraph) and watch both follow. Add a button that doubles the score.
Support: Give the finished run page and ask students only to add the Take a point button.
What two things must you do so a value in setup appears on the page and stays up to date?
Make it with ref and return it from setup, then show it with {{ name }} inside the app.
Next lesson: lists with v-for and choices with v-if. Class idea: list three apps and name the data each one keeps.