beginner
frontend

Vue Template Syntax & Reactivity

Master Vue's template syntax, directives, and deep dive into the reactivity system

vue fundamentals
25 min read

Vue Template Syntax

Vue uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying component instance's data.

What You'll Learn

  • Text interpolation and expressions
  • Attribute bindings with v-bind
  • Event handling with v-on
  • Conditional and list rendering
  • Two-way binding with v-model

Text Interpolation

The most basic form of data binding is text interpolation using the "Mustache" syntax:

vue
<script setup> import { ref } from "vue" const message = ref("Hello, Vue!") const rawHtml = ref('<span style="color: red">This is red</span>') </script> <template> <!-- Text interpolation --> <p>Message: {{ message }}</p> <!-- Expressions in templates --> <p>Reversed: {{ message.split("").reverse().join("") }}</p> <p>{{ 1 + 1 }}</p> <p>{{ ok ? "YES" : "NO" }}</p> <!-- Raw HTML (use with caution!) --> <p v-html="rawHtml"></p> </template>

Directives

Directives are special attributes with the v- prefix. Vue provides many built-in directives:

v-bind

Dynamically bind attributes

v-on

Listen to DOM events

v-if / v-show

Conditional rendering

v-for

List rendering

Attribute Bindings (v-bind)

vue
<script setup> import { ref } from 'vue' const imageUrl = ref('/images/logo.png') const altText = ref('Company Logo') const isDisabled = ref(true) </script> <template> <img v-bind:src="imageUrl" v-bind:alt="altText" /> <button v-bind:disabled="isDisabled">Submit</button> </template>

Event Handling (v-on)

vue
<script setup> import { ref } from 'vue' const count = ref(0) const name = ref('') </script> <template> <!-- Inline handler --> <button @click="count++">Add 1</button> <p>Count: {{ count }}</p> <!-- Accessing event object --> <button @click="(e) => console.log(e.target)"> Log Target </button> </template>

Conditional Rendering

v-if vs v-show
Choose based on your use case

v-if

  • True conditional rendering
  • Element is destroyed/recreated
  • Higher toggle cost
  • Lazy: initial render skipped if false
  • Best for rare toggle scenarios

v-show

  • CSS-based toggling (display: none)
  • Element always in DOM
  • Higher initial render cost
  • No lazy rendering
  • Best for frequent toggles
vue
<script setup> import { ref } from "vue" const isLoggedIn = ref(false) const userRole = ref("admin") const isVisible = ref(true) </script> <template> <!-- v-if / v-else-if / v-else --> <div v-if="isLoggedIn">Welcome back!</div> <div v-else>Please log in</div> <!-- Multiple conditions --> <div v-if="userRole === 'admin'">Admin Panel</div> <div v-else-if="userRole === 'editor'">Editor Panel</div> <div v-else>User Panel</div> <!-- v-if on template (for multiple elements) --> <template v-if="isLoggedIn"> <h1>Title</h1> <p>Content</p> <button>Action</button> </template> <!-- v-show --> <div v-show="isVisible">I toggle with CSS display property</div> </template>

List Rendering (v-for)

vue
<script setup> import { ref } from 'vue' interface User { id: number name: string email: string } const users = ref<User[]>([ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' }, { id: 3, name: 'Charlie', email: 'charlie@example.com' } ]) const object = ref({ title: 'Vue Guide', author: 'Evan You', year: 2024 }) </script> <template> <!-- Array with index --> <ul> <li v-for="(user, index) in users" :key="user.id">{{ index + 1 }}. {{ user.name }} ({{ user.email }})</li> </ul> <!-- Object iteration --> <ul> <li v-for="(value, key, index) in object" :key="key">{{ index }}. {{ key }}: {{ value }}</li> </ul> <!-- Range --> <span v-for="n in 10" :key="n">{{ n }}</span> <!-- With v-if (use template wrapper) --> <template v-for="user in users" :key="user.id"> <li v-if="user.isActive"> {{ user.name }} </li> </template> </template>

Two-Way Binding (v-model)

vue
<script setup> import { ref } from 'vue' const message = ref('') </script> <template> <input v-model="message" placeholder="Type here" /> <p>Message: {{ message }}</p> <!-- v-model is syntactic sugar for: --> <input :value="message" @input="message = $event.target.value" /> </template>

Practice Exercise

Create a Todo List component using what you've learned:

vue
<script setup lang="ts"> import { ref, computed } from "vue" interface Todo { id: number text: string completed: boolean } // TODO: Implement the logic const todos = ref<Todo[]>([]) const newTodo = ref("") const filter = ref<"all" | "active" | "completed">("all") // Computed property for filtered todos const filteredTodos = computed(() => { // Your implementation }) // Methods function addTodo() { // Your implementation } function removeTodo(id: number) { // Your implementation } function toggleTodo(id: number) { // Your implementation } </script> <template> <!-- Your template here --> </template>

Next Steps

Continue Learning
Now that you understand Vue's template syntax, let's learn about components and how to build reusable UI pieces!

Next Lesson

Components & Props