Templates are where most Vue code lives; reading and writing bindings fluently is the first real Vue skill.
A Vue template is valid HTML extended with bindings. Text interpolation uses double curly braces: {{ user.name }} renders the value as text (HTML is escaped, so it is safe against injection).
Inside {{ }} and directive values you write JavaScript expressions, not statements: {{ price * qty }}, {{ ok ? 'Yes' : 'No' }} and {{ formatDate(d) }} work; if blocks and variable declarations do not.
Attributes are not interpolated. To bind one to data, use the `v-bind` directive, almost always with its : shorthand:
:src="avatarUrl",:disabled="isSaving"— afalse,nullorundefinedboolean value removes the attribute.:idalone (same-name shorthand, Vue 3.4+) means:id="id".v-bind="attrsObject"spreads an object of attributes.:[attrName]="value"binds a dynamic attribute name.
:class and :style are special: they accept objects and arrays, so :class="{ active: isActive, 'text-danger': hasError }" toggles classes and merges with a static class attribute.
A directive is an attribute starting with v- whose value is an expression that Vue re-evaluates whenever its reactive dependencies change. You will meet v-if, v-for, v-on and v-model next. v-html renders raw HTML: use it only with content you trust.
Example
<script setup>
import { ref } from 'vue'
const user = ref({ name: 'Ada', avatar: '/ada.png' })
const isSaving = ref(false)
const hasError = ref(true)
const id = 'profile'
</script>
<template>
<section :id> <!-- same as :id="id" -->
<img :src="user.avatar" :alt="`Avatar of ${user.name}`">
<p>{{ user.name.toUpperCase() }}</p> <!-- ADA -->
<p :class="{ error: hasError, saving: isSaving }">Status</p>
<!-- renders class="error" -->
<button :disabled="isSaving">Save</button> <!-- no disabled attr -->
</section>
</template>Remember
{{ expr }}renders escaped text; directives take JavaScript expressions:attr="expr"is shorthand forv-bind:attr; falsy booleans remove the attribute:classand:styleaccept objects and arrays
Watch out for
- Writing
src="{{ url }}"; attributes need:src="url", mustaches only work in text.