Vue templates and interpolations

By

Tagged: Vue.js

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.

Related posts about vue: