Vue.js interprets `<` and `>` in string literal as custom element

This is a great question. Like you, I assumed that everything between the curly braces would be evaluated as an expression and injected into the template. That's what the documentation implies, and in all cases I've encountered this appears to be true... except when there could be an HTML tag in a string literal. At least, that's why my experiments seem to indicate.

Take the following example:

<h1>{{ name || '<span>hello</span>' }}</h1>

There are two ways the parser could read this:

  1. An h1 tag containing curly braces - within those, an expression we need to evaluate later.
  2. An h1 tag followed by the string {{ name || ', then a span, then another string ' }}.

In this case, the parser is built to choose (2), and this explains why you received a compile-time error. The parser indicated that you have a tag starting with <New Document>, but it didn't have a corresponding closing tag.

If this seems like an odd design choice, consider this code:

<h1>{{'<span>hello</span>'}}</h1>

What did the user intend here? Did he/she mean to surround a span with curly braces and quotes? Probably.

As for a solution, you could manually escape the string:

{{ name || '&lt;New Document&gt;' }}

Alternatively, you could solve this with a computed property, which will eschew the template parser altogether:

<template>
  <h1>{{ nameOrNew }}</h1>
</template>

<script>
export default {
  data() {
    return {
      name: false,
    };
  },
  computed: {
    nameOrNew() {
      return this.name || '<New Document>';
    },
  },
};
</script>

Tags:

Vue.Js