Skip to the solution
EasyFrontend9 min read

What is the difference between v-if and v-show?

373 views

The problem

Question presented to candidate: "Both v-if and v-show hide things in a Vue template. What is actually different between them, and how do you decide which one to use?"

What a strong answer should cover:

  • v-if is real conditional rendering: when false the element is not in the DOM (Vue leaves a <!--v-if--> comment placeholder), and a component inside is unmounted, losing its local state; when true it is created and mounted again.
  • v-show always renders the element once and only toggles the inline style display: none; components stay mounted and keep their state.
  • Cost trade-off: v-if has a higher toggle cost but no initial cost when false (lazy); v-show has a higher initial cost but cheap toggles.
  • Rule of thumb: v-show for things toggled often (tabs, dropdowns, accordions); v-if for things rarely shown, or when content should not exist at all (permissions, unmet data).
  • Only v-if supports v-else-if / v-else and works on <template>; v-show does neither.
  • Neither is a security boundary on its own: v-show content is still in the DOM, so never use it to hide data the user must not see.

Clarifying questions expected:

  • "How often does this toggle, and is the hidden part expensive to render?"
  • "Does the hidden part hold state, such as a half-filled form, that must survive?"

Code / implementation expected: Optional. A small demo of the DOM and lifecycle difference is a strong answer.

  • v-if
  • v-show

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 10 sections

Read the code

VueSame child under v-if and v-show: lifecycle logs and whether local state survives
<script setup>
import { ref, defineComponent, h, onMounted, onUnmounted } from "vue";

// A child that reports its own lifecycle and keeps a little local state.
const Panel = defineComponent({
  props: { label: String },
  setup(props) {
    const clicks = ref(0);
    onMounted(() => console.log(`[${props.label}] mounted`));
    onUnmounted(() => console.log(`[${props.label}] unmounted`));
    return () =>
      h("button", { class: props.label, onClick: () => clicks.value++ }, `${props.label}: ${clicks.value} clicks`);
  },
});

const open = ref(false);
</script>

<template>
  <button class="toggle" @click="open = !open">Toggle (open = {{ open }})</button>
  <Panel v-if="open" label="with-v-if" />
  <Panel v-show="open" label="with-v-show" />
</template>

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 16 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextEasy

What are v-model modifiers?

Continue