Templates and Directives
By Syncfusion®, Inc. · Last updated
Declarative rendering, text interpolation with {{ }}, JavaScript expressions in templates and their limits, the parts of a directive, v-bind and its : shorthand, boolean and multiple attributes, v-html and XSS, v-text, v-once, v-memo, v-pre, v-cloak and template scope.
Templates
- A template is the HTML part of a Vue component. It sits inside
<template>. - It looks like normal HTML, with a few extra Vue rules.
- Vue reads the template and builds the page from it.
- When your data changes, Vue updates the page to match the template again.
Simple lesson: the template is a picture of the page. Vue keeps the real page looking like that picture.
A Real-World Example
- Meera's menu card shows a dish name, a price and a "Veg" label.
- The name and price come from her code, not from typed HTML.
- If she changes the price in her code, the card must change too.
- A Vue template does this with
{{ }}and:bindings.
- What happened:
{{ dish }}showed the dish name. {{ isVeg ? "Veg" : "Non-veg" }}picked the right label.:alt="dish"put the dish name inside the image'saltattribute.
What You Will Learn
- What declarative rendering means.
- How to show values with
{{ }}. - Which JavaScript you can write inside a template.
- The parts of a directive.
- How to bind attributes with
v-bindand:. - How to bind boolean attributes and many attributes at once.
- Why
v-htmlcan be dangerous. - What
v-text,v-once,v-memo,v-preandv-cloakdo. - Which names a template can use.
Declarative Rendering
- Declarative = you say what the page should show, not how to change it.
- Imperative = you write every step yourself: find the element, then change its text.
- Vue templates are declarative.
- You never call
document.querySelectorto update text.
| Imperative (plain JavaScript) | Declarative (Vue template) |
|---|---|
el.textContent = "₹" + price | <p>₹{{ price }}</p> |
| You must run it after every change | Vue runs it for you |
| Easy to forget one place | The template is the one place |
Simple lesson: describe the page once. Vue keeps it right.
Text Interpolation
- Interpolation = putting a value inside text.
- Vue uses double curly braces:
{{ value }}. People call them "mustaches". - The value is turned into text.
nullandundefinedshow nothing. An object or array is shown as JSON text.- Vue updates the text when the value changes.
Animation: the value of price flows from the script into the mustache in the template and appears as text on the screen
script price = 90
template
screen ₹90
The mustache is a hole in the text. Vue fills it with the value.
Vue copies the value into the mustache and shows it as text.
JavaScript Expressions
- An expression = a piece of code that gives back a value.
- You can write one expression inside
{{ }}. - Maths:
{{ price * 2 }}. - Text:
{{ dish.toUpperCase() }}. - A choice:
{{ isVeg ? "Veg" : "Non-veg" }}. - A function call:
{{ formatPrice(price) }}.
- What happened: each
{{ }}ran one expression and showed its result.
What You Cannot Write
- Only one expression is allowed. Statements are not.
{{ let total = 5 }}fails. That is a statement.{{ if (isVeg) { ... } }}fails. Use the? :choice instead.- Keep templates simple. Move long logic into a function in the script.
- A function called in the template runs again on every update. For values worked out from state,
computedis better (next lesson but one).
A template error stops the whole component from compiling. The Console names the file and the line, so read it first when the preview stays empty.
Simple lesson: {{ }} shows one expression as text. No statements inside.
The Parts of a Directive
- A directive = a special attribute that starts with
v-. - It tells Vue to do something to that element.
- A directive can have four parts.
Animation: the four parts of v-on:submit.prevent="save" light up one by one. Name, argument, modifier, value
v-on : submit .prevent = "save"
Name: which directive (v-on listens for events) Argument: after the colon (which event: submit) Modifier: after a dot (an extra rule: prevent the page reload) Value: inside the quotes (a JavaScript expression: save)
Name, argument, modifier, value. Not every directive uses all four.
- Name = which directive, such as
v-bindorv-on. - Argument = what it works on, after a colon:
v-bind:href. - Dynamic argument = an argument in square brackets, taken from a variable:
v-bind:[attrName]. - Modifier = an extra rule after a dot:
.prevent. - Value = a JavaScript expression inside the quotes.
Shorthands
v-bind:hrefis written:hrefmost of the time.v-on:clickis written@click. You will learn it in Events and Forms.v-slot:headeris written#header. You will learn it in Slots, Attributes and Provide/Inject.
Simple lesson: a directive is v-name:argument.modifier="value".
Binding Attributes with v-bind
{{ }}only works inside text. It does not work inside an attribute.- To put a value into an attribute, use
v-bind, or:for short. :href="link"means "sethrefto the value oflink".- Without the colon,
href="link"is just the plain text "link". - Same-name shorthand (Vue 3.4): when the variable has the same name as the attribute,
:id="id"can be written:id.
- What happened: the first two links point to the real address.
- The third link points to the text "menuLink", because it has no colon.
:[field]used the variablefield, so it set thetitleattribute.
If an attribute shows your variable's name instead of its value, you forgot the colon.
Boolean Attributes
- A boolean attribute is on or off, such as
disabledorchecked. :disabled="true"adds the attribute.:disabled="false"removes it. So donullandundefined.- An empty string
""keeps the attribute, becausedisabled=""means "on" in HTML. - Here the button turns off when the dish is sold out.
Binding Many Attributes at Once
- You can bind a whole object with
v-bind="object"(no argument). - Each key becomes an attribute.
- This is useful when many attributes belong together.
Simple lesson: use : to put a value into an attribute. Use v-bind="object" for many at once.
v-html and Safety
{{ }}always shows text. HTML tags inside the value appear as plain text.v-htmlputs the value in as real HTML.- That is risky. If the HTML comes from a user, it can run their code.
- This attack is called XSS (cross-site scripting).
- Also,
<style scoped>rules do not reach HTML added byv-html. Style it with a global or:deep()rule.
- What happened: the mustache showed the
<b>tag as text. v-htmlmade the text bold.- The visitor's "review" ran code. The Console below the preview shows it.
Only use v-html for HTML that you wrote or fully trust. Never use it for text typed by users, comments or reviews. Show those with {{ }}.
Simple lesson: {{ }} is safe text. v-html is real HTML, so trust it first.
More Built-In Directives
v-text= sets the whole text of an element. Same as{{ }}for the full content.v-once= shows the value once. Later changes are ignored.v-memo= skips an update unless listed values change. It is for speed in big lists. See Performance.v-pre= shows the template code as it is. Vue skips this part.v-cloak= hides the raw{{ }}until Vue is ready. Only useful with the CDN build.
- What happened: after 1.5 seconds, the first line changed to Pongal.
- The
v-onceline still says Idli. - The
v-preline shows the mustache itself.
v-cloak with the CDN
- With the CDN, the browser shows your HTML before Vue starts.
- For a moment, people can see
{{ special }}on the page. v-cloakplus one CSS rule hides it until Vue is ready.- Build-tool projects compile templates first, so they do not need it.
<style>
[v-cloak] { display: none; }
</style>
<div id="app" v-cloak>{{ special }}</div>
Simple lesson: v-once freezes, v-pre skips, v-cloak hides until ready.
Template Scope
- A template can use everything at the top of
<script setup>: variables, functions and imports. - It can also use a short list of safe globals, such as
Math,Date,JSONandNumber. - It cannot use other globals like
windowordocument. - If you need one, wrap it in a function in the script.
Writing window.innerWidth straight in a template gives a warning that window is not defined, in a real project and in this lab. Calling a script function, as above, works.
Simple lesson: templates see your script's names and a few safe globals.
TL;DR
- Template = the HTML part of a component, inside
<template>. - Declarative = you describe the page, Vue does the updates.
{{ }}= shows one JavaScript expression as text.- Directive = a
v-attribute: name, argument, modifier, value. :attr= short forv-bind:attr. Puts a value into an attribute.- Boolean binding =
:disabled="false"removes the attribute. v-bind="obj"= binds every key of an object as an attribute.v-html= real HTML. Only for HTML you trust.v-once/v-pre/v-cloak= freeze / skip / hide until ready.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
{{ }} inside an attribute | href="{{ link }}" works | Write :href="link" | Vue gives a compile error |
| Forgetting the colon | src="photo" uses the variable | Write :src="photo" | The attribute holds the word photo |
Statements in {{ }} | {{ if (x) ... }} is fine | Use x ? a : b or a function | The template does not compile |
v-html with user text | It is just formatting | Show user text with {{ }} | Strangers can run code on your page (XSS) |
| Long logic in the template | Templates can hold anything | Move it to a function | Hard to read and test |
Using window in a template | All globals work | Wrap it in a script function | A warning, and the value is missing |
v-cloak in a Vite project | Every app needs it | Only CDN pages need it | Extra code that does nothing |
Check Yourself
Exercises
What to Remember
- Templates are declarative: describe the page, Vue updates it.
{{ }}shows one expression as text. It never goes inside an attribute.- Use
:attr="value"to bind attributes. A missing colon means plain text. v-htmlinserts real HTML. Never use it for user text.- A template can use script names and a few safe globals like
Math.
Next: Reactive State