Compare v-show and v-if through DOM cost, lifecycle impact, preserved state, and the performance/debug trade-off between cheap toggles and true unmounting.
Use this Vue interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
How do v-show and v-if differ in DOM behavior and lifecycle impact?Frontend interview answer
This Vue interview question tests whether you can explain v-show vs v-if in Vue: lifecycle cost, preserved state, and toggle-performance trade-offs, connect it to production trade-offs, and handle common follow-up questions.
- v-show vs v-if in Vue: lifecycle cost, preserved state, and toggle-performance trade-offs explanation without falling back to memorized docs wording
- V If and V Show reasoning, edge cases, and production failure modes
- How you would answer the most likely Vue interview follow-up
Performance trade-offv-if and v-show solve different problems. v-if removes the branch and pays mount/unmount cost each time. v-show keeps the instance alive and only toggles CSS display. The real production/debug question is whether you want cheap toggles with preserved state or true teardown with zero hidden work.
Aspect | v-if | v-show |
|---|---|---|
DOM when false | Not in DOM (nodes removed / never created if initially false) | Still in DOM, but hidden via CSS (display:none) |
Component instance | Destroyed when false; recreated when true again | Stays mounted; same instance reused |
Lifecycle hooks | Mount/unmount hooks run on each toggle (Vue 3: mounted/beforeUnmount/unmounted; Vue 2: mounted/beforeDestroy/destroyed) | Mount hooks run once; toggling does not unmount |
Local state (inputs, refs, component data) | Resets on re-mount (new instance) | Preserved across toggles |
Work when hidden | Zero (no render, no DOM patching, no watchers inside because instance is gone) | Still reactive; component can still update/compute even while hidden |
Performance profile | Higher toggle cost, lower steady-state cost when off | Higher initial cost, very cheap toggles |
DOM behavior (plain elements)
• v-if: creates/removes the element. If it starts false, it is lazy (nothing is rendered until it becomes true).
• v-show: element exists, but Vue sets inline display: none when false (removed from layout and accessibility tree).
<template>
<!-- v-if: element is created/removed -->
<div v-if="open">Heavy DOM branch</div>
<!-- v-show: element always exists; only display toggles -->
<div v-show="open">Same DOM node, just hidden</div>
</template>
<script setup>
import { ref } from 'vue';
const open = ref(false);
</script>
Lifecycle impact (components)
With v-if, toggling false unmounts the child component (cleanup runs, subscriptions stop, DOM removed). Toggling true creates a fresh instance, so local state resets.
With v-show, the child stays mounted the whole time; toggling only changes visibility. The instance, refs, and local state remain intact.
<!-- Parent.vue -->
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const show = ref(true);
</script>
<template>
<button @click="show = !show">Toggle</button>
<!-- Swap between these to observe behavior -->
<Child v-if="show" />
<!-- <Child v-show="show" /> -->
</template>
<!-- Child.vue -->
<script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue';
const local = ref(0);
let timerId;
onMounted(() => {
console.log('Child mounted');
timerId = window.setInterval(() => console.log('tick'), 1000);
});
onBeforeUnmount(() => {
console.log('Child beforeUnmount (cleanup)');
window.clearInterval(timerId);
});
</script>
<template>
<button @click="local++">Local state: {{ local }}</button>
</template>
<!-- v-if: local resets after hide/show; cleanup runs.
v-show: local keeps its value; cleanup does NOT run on hide/show. -->
Use case | Prefer | Reason |
|---|---|---|
Frequently toggled UI (tabs, dropdowns, accordions) | v-show | Cheap toggles; preserves state; avoids repeated mount/unmount |
Rarely shown + heavy branch (expensive DOM, large list, complex child) | v-if | Avoid initial render cost; zero work while off |
Need state preserved but also want to avoid background work while hidden | v-if + state lifted (store/composable) or caching (keep-alive where applicable) | Unmount stops work; externalized state prevents losing user input/state |
Common gotchas interviewers like
• v-show does not support v-else/v-else-if chains; v-if does.
• v-show hides via display:none (not just “invisible”); it won’t take space and won’t be reachable by screen readers while hidden.
• Hidden-with-v-show components can still run watchers/computed updates; v-if removes them entirely.
Interview-ready takeawayv-if changes the DOM tree and component lifecycle (mount/unmount, state resets). v-show keeps the same DOM and instance, only toggling display. Use v-show for frequent toggles; use v-if when the branch is rarely needed or expensive and you want zero cost while it’s off.
Use this as one explanation rep, then continue with the Vue.js interview questions cluster or a guided prep path.