AcademyVue
Template Syntax: Interpolation and Bindings
What {{ }} can and cannot render, why every dynamic attribute needs v-bind, and how :class and :style differ from a plain HTML string.
3 min readUpdated 3 exercises
{{ }} renders an expression, not a statement
Vue's mustache syntax evaluates a single JavaScript expression and stringifies the result into the DOM as text:
<template>
<p>{{ user.name }}</p>
<p>{{ items.length }} items</p>
<p>{{ isActive ? 'Online' : 'Offline' }}</p>
</template>An expression, not a statement — {{ if (x) { ... } }} is not valid inside {{ }}, and neither are variable declarations. The ternary above is the idiomatic way to branch inline; anything with real control flow belongs in a computed property or a method, called from the template instead of written into it.
The other thing {{ }} cannot do is render an object usefully. {{ user }} stringifies the whole object via JSON.stringify-like formatting — it is a bug every Vue beginner hits once, and the fix is always the same: reach one level deeper, {{ user.name }}.
Every dynamic attribute needs v-bind
{{ }} only works inside text content. An attribute written as a plain string is exactly that — a string, evaluated never:
<!-- Wrong: renders the literal text "userId" as the id attribute -->
<div id="userId"></div>
<!-- Right: v-bind evaluates the expression -->
<div v-bind:id="userId"></div>
<div :id="userId"></div>:attr is shorthand for v-bind:attr — the two are identical, and every Vue codebase you will read uses the shorthand exclusively. The rule to remember is simple: no colon, no evaluation. This catches beginners specifically on boolean attributes like disabled: writing disabled="isFollowing" sets a real DOM attribute to the literal string "isFollowing", which the browser's boolean-attribute reflection then treats as present — disabling the button permanently, regardless of what isFollowing actually holds.
:class and :style take objects, not strings
Concatenating class names or CSS by hand is the most common Vue anti-pattern outside of the {{ }}-on-attributes mistake above:
<template>
<!-- Works, but string-builds and re-parses on every change -->
<span :class="'item ' + (done ? 'done' : '')"></span>
<!-- Idiomatic: object syntax, each key a class, each value a boolean -->
<span :class="{ item: true, done: done }"></span>
<!-- Same idea for inline styles, camelCase keys -->
<span :style="{ color: done ? 'gray' : 'black', textDecoration: done ? 'line-through' : 'none' }"></span>
</template>The object form composes with a static class attribute on the same element — Vue merges them — and it reads as data rather than as a string you have to mentally re-parse. :style's object form takes camelCase CSS properties (backgroundColor, not background-color), matching the DOM's own CSSStyleDeclaration rather than the stylesheet syntax.
Compilation, not a virtual DOM diff, is why this is fast
A template like the ones above is compiled ahead of time into a render function that Vue's reactivity system re-runs only when the specific values it reads change — a static <footer> with no bindings is hoisted out and never touched again after the first render. That is a different mechanism from React re-rendering a component function and diffing the result: Vue knows, at compile time, exactly which DOM nodes a given piece of state can affect, because the template told it so.
What interviewers check
Whether you can name the failure mode, not just the syntax: forgetting : on a bound attribute, rendering an object through {{ }}, and reaching for string concatenation instead of the object form of :class/:style are the three template-syntax bugs that show up in real codebases and in real interviews.
Now practice it
1 quiz · 2 drillsReading this page is the cheap half. These are the exercises that make you use it.
- Text Interpolation & Attribute BindingFix exactly the three bugs this page names — an object rendered raw, a missing :, and a boolean attribute stuck on.DrillSolve · EasyDrillSolve · Easy
- Class & Style BindingsReplace a hardcoded class and a concatenated style string with the object syntax this page argues for.DrillSolve · EasyDrillSolve · Easy
- Options API · Vue FundamentalsBroader template and directive questions to check the fundamentals stuck beyond these two specific bugs.QuizTake · EasyQuizTake · Easy
Read next
Conditional Rendering and v-for Lists
v-if versus v-show is a cost trade-off, not a style choice, and v-for needs a stable :key for the same reason React needs one on map().
3 min
Event Handling: v-on and Modifiers
Passing a handler versus calling it in the template is the same pitfall React has with onClick, and modifiers replace the boilerplate everyone hand-writes for it.
2 min