Dynamic Rendering
By Syncfusion®, Inc. · Last updated
Class bindings with objects and arrays, classes on components, style bindings with units and CSS variables, v-if, v-else-if and v-else, truthy and falsy conditions, how v-if destroys state, forcing a fresh copy with :key, template groups, v-show, and when to choose v-if or v-show.
Changing the Look from State
- Dynamic rendering = the same template changes its look, or which elements it shows, when the state changes.
- A page often looks different depending on state.
- A sold-out dish is grey. A selected tab is bold. An error message appears only on errors.
Vue does this with three tools:
:classand:stylechange how an element looksv-ifadds or removes an elementv-showhides or shows an element
Simple lesson: state decides how things look and whether they are there.
A Real-World Example
- Meera's menu marks spicy dishes in red.
- Sold-out dishes turn grey, and their button disappears.
- Click the buttons to change the state and watch the card change.
- What happened:
:classaddedspicyandsold-outwhen they were true. v-ifandv-elseswapped the button for the "Sold out" text.
What You Will Learn
- How to switch classes with an object.
- How to list classes with an array.
- What happens to classes on a component.
- How to set styles from state, with units and CSS variables.
- How
v-if,v-else-ifandv-elsework together, and what counts as true. - Why
v-ifresets state, and how:keyforces a fresh copy. - How
v-showis different. - When to pick
v-ifand when to pickv-show.
Class Bindings
Object Syntax
:class="{ name: condition }"adds the class when the condition is true.- You can list many classes in one object.
- Names with a dash need quotes:
'sold-out': soldOut. - A normal
class="..."can sit next to:class. Vue joins them.
Object from a computed
- Long class objects make the template hard to read.
- Move them into a
computedvalue.
Array Syntax
:class="[a, b]"adds the class names stored inaandb.- You can mix in a choice:
[size, isNew ? 'new' : '']. - You can also put an object inside the array.
Classes on Components
- You can put
classor:classon your own component, too. - Vue adds those classes to the component's root element.
- If the component has several root elements, Vue does not know where to put them. The class is dropped, and Vue warns. The child must place it with
v-bind="$attrs". - You will learn more in Slots, Attributes and Provide/Inject.
- What happened: the
spangot bothbadgeandhot.
Simple lesson: use an object to switch classes on and off. Use an array to list them.
With <style scoped>, a parent's class on a child component still styles the child's root element. Inner elements need :deep(). You will see this in Components and Single-File Components.
Style Bindings
:stylesets inline styles from state.- Use an object. Write names in camelCase (
fontSize) or in quotes ('font-size'). - Add units.
{ width: size }with a plain number does nothing. Writesize + 'px'or a template string. - An array joins many style objects.
- Vue adds browser prefixes for you when a property needs them.
Prefer :class over :style. Classes keep the CSS in one place. Use :style for values that really come from data, such as a width in pixels or a colour picked by the user.
CSS Variables from State
- A CSS variable (custom property) has a name starting with
--, like--accent. - Set it with
:style="{ '--accent': colour }"on a parent. - Every rule inside can use it with
var(--accent). One value themes many elements.
- What happened: the slider changed one width. The colour picker changed one variable, and the border, bar, button and text all followed.
Simple lesson: :style takes an object of CSS properties (with units), or an array of them. CSS variables theme many elements at once.
Conditional Rendering
v-if, v-else-if and v-else
v-if="condition"adds the element only when the condition is true.v-else-ifgives another condition to try.v-elseis used when nothing above was true.- They must sit right after each other, with nothing in between.
Grouping with template
- To show or hide many elements together, wrap them in
<template v-if>. - The
<template>tag itself is not added to the page.
What Counts as True
- The condition does not have to be
trueorfalse. Vue checks if it is truthy. - Falsy values:
false,0,""(empty text),null,undefinedandNaN. Everything else is truthy, even"0",[]and{}. - Trap:
v-if="count"hides the element when the count is 0. - Trap:
v-if="items"is true even for an empty array. Checkitems.lengthinstead. - Write the real question:
count > 0,items.length > 0,name !== ''.
- What happened: line A was missing while the count was 0. Line C showed for an empty array.
v-if Destroys and Rebuilds
- When a
v-ifturns false, Vue destroys the element and every component inside it. - Their state is gone: typed text, counters, timers.
onUnmountedruns. - When it turns true again, Vue builds a new copy.
onMountedruns again, and the state starts fresh. v-showkeeps the same copy, so its state survives.- Use this on purpose:
v-ifto reset a form,v-showto keep what the user typed.
- Type in both boxes, then press Hide and Show.
- What happened: the
v-ifbox came back empty, and the Console shows it was destroyed and mounted again. Thev-showbox kept your text.
Forcing a Fresh Copy with :key
- In Vue 3, each
v-if/v-elsebranch gets its own key automatically. Two branches are always two separate elements. - (Old Vue 2 tutorials say you must add
keytov-ifbranches. In Vue 3 you do not.) - But when the same element stays on the page and only its data changes, Vue keeps the old copy and its state.
- Give it
:key="value". When the value changes, Vue destroys the old copy and builds a fresh one. - Typical use: reset a form when the user picks another table, order or customer.
- Type a note in both forms, then press Next table.
- What happened: the first form kept the old table's note. The keyed form came back empty, and the Console shows a fresh copy.
Simple lesson: v-if adds or removes elements, and a removed element loses its state. Write clear conditions, and change :key to get a fresh copy.
v-show
v-show="condition"always keeps the element on the page.- It only switches
display: noneon and off. - It does not work with
<template>or withv-else.
Animation: when the condition turns false, v-if removes the element from the page tree, while v-show keeps the element but sets display none
v-if v-show
div
p (menu) div
p (menu) style="display: none" removed from the page
The condition turns false: v-if removes, v-show hides.
v-if takes the element out. v-show keeps it but hides it.
- What happened: after a toggle, both lines disappear.
- But "Count elements" shows the
v-showline is still on the page, just hidden.
Which One to Pick
| Point | v-if | v-show |
|---|---|---|
| When false | Element is removed | Element stays, display: none |
| Start cost | Cheap if false at the start | Always builds the element |
| Toggle cost | Higher: build and remove | Low: just a style change |
Works with v-else and <template> | Yes | No |
| State inside when hidden | Lost, rebuilt fresh | Kept |
| Best for | Rarely changes, or should reset | Changes often, like a dropdown |
Do not put v-if and v-for on the same element. You will see why in List Rendering.
Simple lesson: v-if for things that rarely change. v-show for things that toggle often.
TL;DR
:class="{ a: cond }"/:class="[x, y]"= switch classes on and off / list class names.- Class on a component = goes to the component's root element.
:style="{ width: w + 'px', '--accent': c }"= inline styles and CSS variables. Add units.v-if/v-else-if/v-else= add or remove elements. Must come right after each other.- Truthy =
0,"",null,undefinedare false.[]and{}are true. v-ifand state = false destroys the element and its state. A new:keyforces a fresh copy.<template v-if>= groups elements without adding a tag.v-show= keeps the element, togglesdisplay: none.- Pick =
v-iffor rare changes,v-showfor frequent toggles.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Dash class without quotes | { sold-out: x } is fine | Write { 'sold-out': x } | A compile error |
class="{ active: x }" | Plain class reads objects | Use :class | The class is the text { active: x } |
Something between v-if and v-else | v-else finds its v-if anywhere | Put them right next to each other | A compile error |
v-show with v-else | They work together | Use v-if with v-else | Compile error: v-else has no adjacent v-if |
v-if="count" for a number | Any number is true | Write count > 0 | Hidden when the count is 0 |
v-if="items" for a list | Empty lists are false | Check items.length | Shown even when empty |
{ width: size } | Vue adds px | Write size + 'px' | The style is ignored |
| Same component, new data, old state | New props reset the state | Add :key that changes with the data | Old typed text stays |
v-show on <template> | It hides the group | Use v-if, or a real wrapper element | Nothing is hidden |
v-if on a fast toggle | It is always best | Use v-show for frequent toggles | Extra work on every toggle |
| Long objects in the template | It is fine in the template | Move them to a computed | Hard to read |
Check Yourself
Exercises
What to Remember
:classtakes an object (switch on and off) or an array (list of names).:styletakes an object of CSS properties, or an array of objects.v-ifadds and removes.v-else-ifandv-elsemust follow it directly.<template v-if>groups elements without an extra tag.v-showhides with CSS. Use it for frequent toggles.
Next: List Rendering