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:

    • :class and :style change how an element looks
    • v-if adds or removes an element
    • v-show hides 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: :class added spicy and sold-out when they were true.
  • v-if and v-else swapped the button for the "Sold out" text.

What You Will Learn

  1. How to switch classes with an object.
  2. How to list classes with an array.
  3. What happens to classes on a component.
  4. How to set styles from state, with units and CSS variables.
  5. How v-if, v-else-if and v-else work together, and what counts as true.
  6. Why v-if resets state, and how :key forces a fresh copy.
  7. How v-show is different.
  8. When to pick v-if and when to pick v-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 computed value.

Array Syntax

  • :class="[a, b]" adds the class names stored in a and b.
  • You can mix in a choice: [size, isNew ? 'new' : ''].
  • You can also put an object inside the array.

Classes on Components

  • You can put class or :class on 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 span got both badge and hot.

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

  • :style sets 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. Write size + '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-if gives another condition to try.
  • v-else is 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 true or false. Vue checks if it is truthy.
  • Falsy values: false, 0, "" (empty text), null, undefined and NaN. 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. Check items.length instead.
  • 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-if turns false, Vue destroys the element and every component inside it.
  • Their state is gone: typed text, counters, timers. onUnmounted runs.
  • When it turns true again, Vue builds a new copy. onMounted runs again, and the state starts fresh.
  • v-show keeps the same copy, so its state survives.
  • Use this on purpose: v-if to reset a form, v-show to keep what the user typed.
  • Type in both boxes, then press Hide and Show.
  • What happened: the v-if box came back empty, and the Console shows it was destroyed and mounted again. The v-show box kept your text.

Forcing a Fresh Copy with :key

  • In Vue 3, each v-if / v-else branch gets its own key automatically. Two branches are always two separate elements.
  • (Old Vue 2 tutorials say you must add key to v-if branches. 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: none on and off.
  • It does not work with <template> or with v-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-show line is still on the page, just hidden.

Which One to Pick

Pointv-ifv-show
When falseElement is removedElement stays, display: none
Start costCheap if false at the startAlways builds the element
Toggle costHigher: build and removeLow: just a style change
Works with v-else and <template>YesNo
State inside when hiddenLost, rebuilt freshKept
Best forRarely changes, or should resetChanges 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, undefined are false. [] and {} are true.
  • v-if and state = false destroys the element and its state. A new :key forces a fresh copy.
  • <template v-if> = groups elements without adding a tag.
  • v-show = keeps the element, toggles display: none.
  • Pick = v-if for rare changes, v-show for frequent toggles.

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
Dash class without quotes{ sold-out: x } is fineWrite { 'sold-out': x }A compile error
class="{ active: x }"Plain class reads objectsUse :classThe class is the text { active: x }
Something between v-if and v-elsev-else finds its v-if anywherePut them right next to each otherA compile error
v-show with v-elseThey work togetherUse v-if with v-elseCompile error: v-else has no adjacent v-if
v-if="count" for a numberAny number is trueWrite count > 0Hidden when the count is 0
v-if="items" for a listEmpty lists are falseCheck items.lengthShown even when empty
{ width: size }Vue adds pxWrite size + 'px'The style is ignored
Same component, new data, old stateNew props reset the stateAdd :key that changes with the dataOld typed text stays
v-show on <template>It hides the groupUse v-if, or a real wrapper elementNothing is hidden
v-if on a fast toggleIt is always bestUse v-show for frequent togglesExtra work on every toggle
Long objects in the templateIt is fine in the templateMove them to a computedHard to read

Check Yourself

Exercises

What to Remember

  • :class takes an object (switch on and off) or an array (list of names).
  • :style takes an object of CSS properties, or an array of objects.
  • v-if adds and removes. v-else-if and v-else must follow it directly.
  • <template v-if> groups elements without an extra tag.
  • v-show hides with CSS. Use it for frequent toggles.

Next: List Rendering