Vue templates and interpolations
By Flavio Copes
Learn how Vue 3 templates work as a superset of HTML, where you output component state with interpolation and add behavior with directives like v-bind.
Vue.js uses a templating language that’s a superset of HTML.
Any HTML is a valid Vue template. On top of that, Vue gives you interpolation and directives.
This is a valid Vue template:
<span>Hello!</span>
You can put it in the template property of a component created with createApp:
import { createApp } from 'vue'
createApp({
template: '<span>Hello!</span>'
}).mount('#app')
Template strings like this one are compiled in the browser, so they need the Vue build that ships the compiler. The CDN build has it. The default vue import in a Vite project does not, so in a Vite project you write the template in a Single File Component instead:
<template>
<span>Hello!</span>
</template>
Next step: print a piece of state, for example a name.
You add it to data, then interpolate it in the template with double braces:
import { createApp } from 'vue'
createApp({
data() {
return {
name: 'Flavio'
}
},
template: '<span>Hello {{ name }}!</span>'
}).mount('#app')
In Vue 3, data is always a function that returns an object. Vue 2 allowed a plain object on the root instance, Vue 3 does not.
One interesting detail: in the template you write name, not this.data.name. Vue binds the state into the template for you.
In a Single File Component:
<template>
<span>Hello {{ name }}!</span>
</template>
<script>
export default {
data() {
return {
name: 'Flavio'
}
}
}
</script>
Or with <script setup> (common in Vue 3 apps):
<template>
<span>Hello {{ name }}!</span>
</template>
<script setup>
import { ref } from 'vue'
const name = ref('Flavio')
</script>
In the template you still write name. Vue unwraps refs for you there.
I used a regular function for Options API data. Why not an arrow function?
Because data might need this, and arrow functions do not bind this to the instance. Safer to stick with a normal function.
What you can put in {{ }}
{{ name }} looks like Mustache / Handlebars, but Vue is more flexible.
You can use any JavaScript expression, limited to one expression:
{{ name.split('').reverse().join('') }}
{{ name === 'Flavio' ? 'Flavio' : 'stranger' }}
Vue also exposes a few globals in templates, including Math and Date:
{{ Math.sqrt(16) * Math.random() }}
A short expression is fine in the template. When it grows, move it to a computed property or a method, so the template stays readable.
The interpolated value updates every time the data it depends on changes, unless you use the v-once directive, which renders it once and skips later updates.
Interpolation escapes HTML, so you can’t output raw markup through {{ }}. If you really need that, use the v-html directive, and only with content you trust, because untrusted HTML there is an XSS risk.
Want me to talk about your product? You can sponsor this site.