Template Interpolation
Chapter 1's interpolated values were constants that never changed. The moment a value needs to change and have the UI update, it must be reactive — Vue's tracking system that re-renders the template when a value changes. In the Composition API, the core tool for that is ref.
ref — A Reactive Value
ref(0) creates a reactive container holding 0. The catch that trips up everyone at first: in the <script>, you read and write the value through .value (count.value++) — but in the <template>, Vue unwraps it automatically, so it's just {{ count }}, no .value. This is Vue's equivalent of React's useState, but with two key differences: there's no separate setter function (you assign to .value directly), and the same ref is used both to read and to update.
<script setup>, always use count.value. Inside <template>, always use plain count — Vue unwraps it for you there. Forgetting .value in the script (writing count++) silently fails to update anything; adding .value in the template ({{ count.value }}) shows undefined.
Why Not a Plain Variable?
A plain let count = 0 increments fine in memory, but Vue isn't tracking it — nothing tells the framework the UI needs re-rendering, so the displayed number never changes. Exactly the same trap as a plain variable in React (Fundamentals Chapter 3). ref is what makes the value reactive; the change to .value is what Vue detects.
reactive — For Objects
reactive is an alternative for objects, making the whole object reactive with no .value — properties are accessed directly (state.age++). In practice, many Vue developers use ref for everything (it works for objects too, via ref({...}).value) to avoid juggling two mental models, but reactive is common and worth recognizing. The trade-off: reactive only works on objects/arrays, and you lose reactivity if you destructure it.
Expressions in the Template
Interpolation isn't limited to a bare value — any single JavaScript expression works inside {{ }}: arithmetic, method calls, ternaries. The same as React's curly braces, and like Angular's interpolation, it's expressions only (no statements like if or for — those have their own directives, next chapter).
| React useState | Vue ref | |
|---|---|---|
| Create | const [c, setC] = useState(0) | const c = ref(0) |
| Read (script) | c | c.value |
| Read (markup) | {c} | {{ c }} |
| Update | setC(c + 1) | c.value++ |
Coding Challenges
Build a counter with a ref starting at 0 and a +1 button that increments it (remembering .value in the function), displaying the count via interpolation.
📄 View solutionBuild a component with a reactive object (via reactive) holding firstName and lastName, plus a button that changes one of them, displaying "Full name: [first] [last]" with both updating live.
📄 View solutionBuild a component with a price ref and a quantity ref, displaying their product directly in the template as a {{ }} expression (price * quantity), with buttons to change each — confirming the total recomputes automatically.
📄 View solutionChapter 2 Quick Reference
- ref(value) — a reactive value; Vue's equivalent of
useState - Read/write with .value in
<script>; use the plain name (auto-unwrapped) in<template> - No separate setter — assign to
.valuedirectly (count.value++) - A plain variable won't trigger UI updates — only a
ref(orreactive) is tracked - reactive({...}) — makes an object reactive with no
.value; objects/arrays only - {{ }} accepts any single JS expression (math, method calls, ternaries)
- Next chapter: directives —
v-bind,v-on,v-model