Vue templates and interpolations

By

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.

Tagged: Vue.js · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about vue: