How do v-show and v-if differ in DOM behavior and lifecycle impact?

LowIntermediateVue
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

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.

Answer

Core difference

v-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

v-if vs v-show: DOM + lifecycle impact

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).

HTML
<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.

HTML
<!-- 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

How to choose

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 takeaway

v-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.

Similar questions
Guides
20 / 34