Contents8

2026 update: this post was first written for Vue 2 / Options API. In 2026, Vue 3 with the Composition API (<script setup>) is the default, but the template syntax for v-if / v-else / v-for hasn’t changed, so the shape of the examples below still maps over.

A short reference for the Vue.js directives that handle conditional rendering and iteration.

The mustache syntax and v-bind are covered in a separate post.

The short answer

  • v-if: renders the element only when the condition is truthy. Pairs with v-else / v-else-if
  • v-show: toggles visibility through CSS display. Suited to elements that flip on and off often
  • v-for: iterates over an array. Always pass :key

v-if

v-if renders an element only when the expression is truthy.

It’s common in real work — UI that needs to differ between mobile and desktop, or between logged-in and logged-out states, is the typical case.

Basic usage

v-if is written as an attribute on the target element, with the condition as its value.


The snippet below decides inside the template whether the block renders.

In practice this displays This is a sample.

<template>
  <div v-if="sampleNum === 1">
    サンプルです。
  </div>
</template>

<script>
export default {
  data() {
    return {
      sampleNum: 1
    };
  },
};
</script>

v-else

v-if accepts an else branch in the same way a regular if statement does.

Just add v-else as an attribute on the next element.


This snippet displays else is shown.

<template>
  <div>
    <div v-if="sampleNum === 0">
      サンプルです。
    </div>
    <div v-else>
      elseが表示です。
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sampleNum: 1
    };
  },
};
</script>

One gotcha: v-else has to sit on the element directly after the v-if. Anything in between breaks the pairing.

v-else-if

else-if works alongside else.

The form is the same — add v-else-if as the attribute.


This snippet displays sampleNum is 1.

<template>
  <div>
    <div v-if="sampleNum === 0">
      サンプルです。
    </div>
    <div v-else-if="sampleNum === 1">
      sampleNumは1です。
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      sampleNum: 1
    };
  },
};
</script>

v-show

v-show looks similar to v-if from the outside, but the mechanics are different.

The syntax matches v-if — write v-show="..." as an attribute.


The difference between v-if and v-show is whether the DOM node is added and removed, or just hidden with display.

v-if creates the element when the condition turns truthy and removes it from the DOM when the condition turns falsy. v-show keeps the element in the DOM from the start and only toggles display: none. As a result, the toggle cost is lower with v-show, while the initial-render cost is lower with v-if.

A rough rule of thumb:

  • Element that’s likely falsy at first paint and rarely shown after — v-if
  • Toggle UI that flips on and off frequently — v-show

Note that v-show leans on the display property, so it doesn’t compose with <template> elements or with v-else. In those cases, use v-if.

v-for

v-for iterates over an array or object and renders the template once per entry.

It maps closely to a JavaScript for loop — Vue lays out the same template for each item in the list.

The form is v-for="(item, index) in list". Pass a unique value to :key so Vue can diff the list correctly.


This snippet displays num is 1, index is 0. num is 2, index is 1.

<template>
  <div>
    <div v-for="(num, i) in numList" :key="i">
      中身は{{ num }}, indexは{{ i }}。
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      numList: [1, 2]
    };
  },
};
</script>

Wrapping up

v-if creates or removes the element based on the condition; v-show keeps the element and hides it with CSS. v-for needs :key to iterate cleanly. The template syntax carries over to Vue 3 unchanged, so this same shape works once you move to the Composition API.

Related posts: