v-if adds/removes elements from the DOM (mount/unmount lifecycle), while v-show toggles display via CSS and keeps elements in the DOM. Use v-if for expensive components; v-show for frequent toggles.
How do v-show and v-if differ in DOM behavior and lifecycle impact?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core differencev-if is structural: the branch exists only when the condition is true (DOM nodes are created/inserted and later removed).v-show is presentational: the element/component is always rendered once, and Vue toggles visibility by setting style.display (typically display: none).
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.