Progressive Vue

Template Syntax ≒ HTML

Templates Are HTML

Before learning Vue's template syntax, let me state the most important point.

Vue templates are valid HTML.

Unlike JSX, you don't write HTML inside JavaScript.
You write HTML, and add just a few Vue-specific attributes.
The browser's HTML parser can interpret them as legitimate HTML.

This is at the core of Vue's design philosophy.

Mustache Syntax: {{ }}

To display data in the template, use {{ }} (Mustache syntax).

Let's start with the simplest example.

<div id="app">
  <h1>{{ message }}</h1>
</div>

<script type="importmap">
  { "imports": { "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js" } }
</script>
<script type="module">
  import { createApp, ref } from 'vue'

  createApp({
    setup() {
      const message = ref('My Bookshelf')
      return { message }
    }
  }).mount('#app')
</script>

{{ message }} gets replaced with the value of message defined in setup().
The rest of the template remains just HTML.

v-for: Loops

Instead of copy-pasting HTML, generate a list from an array.

<div id="app">
  <h1>My Bookshelf</h1>
  <p>A record of recently read books.</p>

  <div class="card" v-for="book in books">
    <h2>{{ book.title }}</h2>
    <p>{{ book.description }}</p>
    <span class="tag" v-for="tag in book.tags">
      {{ tag }}
    </span>
  </div>
</div>

v-for="book in books" — this is a Vue directive.
It's written as an HTML attribute, right where you'd write class or id.

Notice that the template structure is nearly identical to the static HTML from the previous chapter.

Static HTML Vue Template
<div class="card"> <div class="card" v-for="book in books">
<h2>Readable Code</h2> <h2>{{ book.title }}</h2>
<span class="tag">programming</span> <span class="tag" v-for="tag in book.tags">{{ tag }}</span>

The HTML structure stays the same. One attribute added, text replaced with {{ }}.
This is the template DSL (Domain Specific Language). It extends HTML without breaking it.

v-bind: Attribute Binding

You can bind data to HTML attributes, not just text content.

<a v-bind:href="book.url">{{ book.title }}</a>

There's a shorthand — just :.

<a :href="book.url">{{ book.title }}</a>

Again, written in the HTML attribute position.
Not special syntax — just binding data to an attribute value.

v-if / v-else: Conditional Rendering

<div class="card" v-for="book in books">
  <h2>{{ book.title }}</h2>
  <p>{{ book.description }}</p>
  <p v-if="book.tags.length === 0">No tags</p>
  <div v-else>
    <span class="tag" v-for="tag in book.tags">
      {{ tag }}
    </span>
  </div>
</div>

v-if is also an HTML attribute. Use it the same way you'd write the hidden attribute.

Templates Are Not "Another Language"

React's JSX is a JavaScript extension. You need a transpiler like Babel to use it.
Angular's templates have many proprietary constructs that drift far from HTML.

Vue templates are HTML itself, with just a few attributes (v-for, v-if, v-bind) and {{ }}.

  • If you can read HTML, you can read Vue templates
  • They're visible as-is in browser DevTools
  • HTML validators (mostly) accept them

Templates being HTML — this is one of Vue's greatest strengths.

Summary

  • Vue templates are valid HTML with directives added
  • {{ }} displays data
  • v-for generates lists (written as HTML attributes)
  • v-bind (:) binds data to attributes
  • v-if / v-else for conditional display
  • Template structure stays nearly identical to static HTML
  • Still just a single index.html file

Related

Back to book