Template Syntax
Vue templates are HTML extended with a small set of special syntax. Most of it is intuitive once you see it, and it compiles away — the browser never sees Vue syntax, only the rendered HTML.
Text interpolation
Section titled “Text interpolation”Use {{ }} to render a value as text:
<script setup lang="ts">const name = 'Alice'const year = 2024</script>
<template> <p>{{ name }}</p> <p>Year: {{ year }}</p></template>The expression inside {{ }} is evaluated as JavaScript. If name is a ref, Vue auto-unwraps it — write {{ name }}, not {{ name.value }}.
JavaScript expressions
Section titled “JavaScript expressions”Any single JavaScript expression works inside {{ }}:
<template> <p>{{ name.toUpperCase() }}</p> <p>{{ 2 + 2 }}</p> <p>{{ isAlive ? 'Living' : 'Deceased' }}</p> <p>{{ person.name || 'Unknown' }}</p></template>The key constraint: expressions only, not statements. {{ if (x) { } }} is invalid. {{ x ? 'yes' : 'no' }} is fine. If you need complex logic, compute it in <script setup> and reference the result.
Attribute binding with v-bind
Section titled “Attribute binding with v-bind”Static HTML attributes like class="card" work as normal. For dynamic attributes — values that come from your script — use v-bind:
<script setup lang="ts">const imageUrl = '/avatar.png'const isActive = true</script>
<template> <img v-bind:src="imageUrl" v-bind:alt="name" /> <div v-bind:class="isActive ? 'card active' : 'card'"></div></template>The shorthand for v-bind: is just : — you will see this everywhere:
<img :src="imageUrl" :alt="name" /><div :class="isActive ? 'card active' : 'card'"></div>Raw HTML
Section titled “Raw HTML”{{ }} always renders content as text, never HTML. If you render '<strong>bold</strong>' with interpolation, you’ll see the literal angle brackets — not bold text. To render raw HTML you use v-html, but avoid it for user-supplied content (XSS risk).
Template restrictions
Section titled “Template restrictions”Templates have a few restrictions worth knowing:
- Each template should have a single root element in practice (though Vue 3 technically allows multiple)
- You cannot use
console.logor other global browser APIs directly in templates — compute the value in<script setup>first - Multi-line expressions inside
{{ }}are hard to read — prefer computed properties
Exercise
Section titled “Exercise”- In
PersonCard.vue, add aconst name = 'Alice'and aconst birthYear = 1982in the script. - Use
{{ name }}and{{ birthYear }}in the template. - Add a
const isDeceased = falseand use a ternary to display “Living” or “Deceased”. - Add an
:titleattribute to the card div that shows the person’s name on hover.
{{ expression }}renders a JavaScript expression as text; refs are auto-unwrapped.- Only expressions work inside
{{ }}— no statements likeiforfor. v-bind:attr="value"dynamically binds an attribute; shorthand is:attr="value".- For complex logic, compute the value in
<script setup>and reference the result in the template.