skip to content

In Vue 3, how do v-if and v-show differ, and which would you use for a dropdown versus a rarely opened admin panel?

level: juniorimportance: must knowfreq 82%

answer

  1. render versus display
  2. lazy on first render
  3. toggle cost against initial cost
  4. often toggled, or rarely shown

basics

~20 s

Vue's v-if adds and removes its block, destroying child components and listeners, and renders nothing while false; v-show always renders and only toggles inline display. Use v-show for a frequently toggled dropdown, v-if for a rarely shown admin panel.

solid answer

~40 s

`v-if` is **real conditional rendering**: while false, Vue renders only a comment placeholder; when it flips, the block's elements, directives and child components are created, and when it flips back they are unmounted and their state discarded. It is also **lazy**, so a block that starts false costs nothing until first shown. `v-show` **always renders** the element and its children, then toggles the inline `display` style, so hidden children are mounted and live. The guide's rule: `v-if` has higher **toggle** cost, `v-show` higher **initial render** cost. A dropdown opened dozens of times per session suits `v-show`; an admin panel most users never open suits `v-if`, which also keeps its components from mounting at all. `v-show` does not work on `<template>` and cannot pair with `v-else`.

go deeper

for a junior

Remember that v-if adds and removes the block while v-show only toggles display, and that v-show cannot pair with v-else or sit on <template>.

for a middle

Explain laziness, the toggle-versus-initial-cost rule, and that hidden v-show children are fully mounted and reactive.

for a senior

Choose per case from toggle frequency, subtree cost and side effects in hidden children, such as polling or fetching you did not intend to start.

for a principal

Set guidance for heavy optional features, such as admin tools or wizards, that combines lazy creation with cheap toggling instead of a blanket rule.

## Two directives, two mechanisms Both directives take an expression and use its truthiness, but they work at different layers. - **`v-if`** decides whether the block exists in the virtual DOM at all. When the expression is falsy Vue renders a **comment placeholder** in its place (it reads `v-if` in development builds). When it becomes truthy, Vue creates the elements, runs their directives and mounts any child components. When it becomes falsy again, all of that is **unmounted**: listeners are removed, child components run their unmount hooks and their local state is gone. - **`v-show`** always renders the element and everything inside it. It is a built-in directive that writes the element's inline `display` style: `none` while falsy, and the element's **original inline display value** while truthy. ## The cost trade-off Vue's guide sums it up in one sentence: `v-if` has higher toggle costs, `v-show` has higher initial render costs. | | `v-if` | `v-show` | |---|---|---| | Initially false | renders nothing (lazy) | renders everything, hidden | | Each toggle | mount or unmount the whole block | one inline style write | | Child components while hidden | do not exist | mounted, reactive, running | | Local state across toggles | discarded on hide | kept | | `<template>` wrapper | supported | not supported | | `v-else` / `v-else-if` | supported | not supported | Because hidden `v-show` content is fully alive, its child components run `setup`, start any watchers and may fire network requests even if the user never opens it. With `v-if`, none of that happens until the condition is first true. ## Applying it: the dropdown and the admin panel 1. **A header dropdown** that users open and close many times per session is small, cheap to render once and toggled often. `v-show="open"` renders it once and afterwards only flips `display`, so opening feels instant and its scroll position and highlighted item survive closing. 2. **An admin-only settings panel** that most users never see, and that pulls in heavy child components, should use `v-if="isAdmin && panelOpen"`. Non-admins pay nothing for it: no components mounted, no requests fired, no listeners attached. The rule of thumb is "how often does it flip, and how expensive is it to create?", not "which one is faster". ## Restrictions worth remembering - `v-show` **cannot** be used on `<template>`, because there is no element whose style it could set. Use `v-if` on `<template>` to toggle a group of siblings, or wrap them in a real element for `v-show`. - `v-show` has no `v-else`. For an either/or display with `v-show`, write two elements with opposite conditions. - On a component, `v-show` is applied to the component's root element, so it needs a component with a **single element root**; in development Vue warns about runtime directives on a non-element root. - Both directives trigger `<Transition>` enter and leave animations when wrapped in one. ## Common interview mistakes - Saying `v-show` removes the element, or that `v-if` just sets `display: none`. - Claiming `v-show` is always faster: it is slower on first render when the content is large and rarely shown. - Forgetting that hidden `v-show` children are running, which matters for polling, timers and data fetching. - Reaching for `v-show` to keep a form's typed values without realising the whole subtree is also rendered for users who never open it.

  • Does a child component inside a hidden `v-show` block in Vue 3 run its `setup` and `onMounted`?
    Yes. `v-show` only sets `display: none`; the element and its subtree are rendered and mounted like any other, so `setup` runs, `onMounted` fires and watchers or requests inside it start even though nothing is visible.
  • How would you get `v-if`'s lazy first render but `v-show`'s cheap toggling in Vue 3?
    Gate the block with `v-if` on a flag that becomes true the first time it is opened and never goes back, and toggle visibility with `v-show` on an inner element. The content mounts on first use and is then only hidden and shown.

v-show is a light switch on a room that is always furnished; v-if is building the room when someone wants to enter and demolishing it when they leave.

saying these in an interview costs you the question

  • v-show removes the element from the DOM when false.
  • v-if only sets display none under the hood.
  • v-show is always the faster choice.
  • Children of a hidden v-show block are not mounted.
  • v-show can be paired with v-else like v-if.