Roadmap › Vue.js 3 (with Pinia, Vue Router & Nuxt basics) › Module: Basics
Lessons in this course (17)
2. Template syntax and directives
Basic★ Must knowLesson 2 of 17
vue
<template>
<p>{{ message.toUpperCase() }}</p> <!-- interpolation (escaped) -->
<p v-html="trustedHtml"></p> <!-- raw HTML: XSS risk with user input -->
<img :src="product.image" :alt="product.name" /> <!-- v-bind shorthand ':' -->
<button @click="addToCart(product)">Add</button> <!-- v-on shorthand '@' -->
<form @submit.prevent="save"> <!-- event modifiers: .prevent .stop .once .self -->
<input v-model.trim="name" @keyup.enter="save" /> <!-- v-model modifiers: .trim .number .lazy -->
</form>
<p v-if="orders.length === 0">No orders</p>
<p v-else-if="loading">Loading…</p>
<ul v-else>
<li v-for="(o, index) in orders" :key="o.id">{{ index + 1 }}. {{ o.customer }}</li>
</ul>
<div v-show="isOpen">Toggled with CSS display</div>
<span v-once>{{ initialValue }}</span> <!-- render once -->
<component :is="currentTab" /> <!-- dynamic component -->
</template>| Directive | Purpose |
|---|---|
v-bind / : | Bind attribute/prop |
v-on / @ | Listen to events |
v-model | Two-way binding on inputs/components |
v-if / v-else-if / v-else | Conditional rendering (creates/destroys) |
v-show | Toggle display (stays in DOM) |
v-for | Lists (always with :key) |
v-html, v-text | Raw HTML / text |
v-slot / # | Named/scoped slots |
v-once, v-memo, v-pre, v-cloak | Render optimisation / skip compilation |
Avoid v-if and v-for on the same element (in Vue 3 v-if has higher priority) — filter in a computed property or wrap with <template>.