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?
answer
- render versus display
- lazy on first render
- toggle cost against initial cost
- often toggled, or rarely shown
basics
~20 sVue'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
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>.
Explain laziness, the toggle-versus-initial-cost rule, and that hidden v-show children are fully mounted and reactive.
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.
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.