# v-if で表示・非表示を切り替える

購入しようと思った商品が売り切れで購入できないと、せっかく購入しようとしたユーザーをがっかりさせてしまいます。そこで、売り切れの商品は非表示にしてみましょう。

# v-if の書き方

Vue.js では特定の条件の時だけ DOM を生成し表示できる、v-if というディレクティブが用意されています。以下のように、表示・非表示を制御したい DOM 要素に v-if を追加します。v-if の値が true の場合は表示され、 false の場合は表示されません。

<!-- 表示される -->
<div v-if="true">something</div>

<!-- 表示されない -->
<div v-if="false">something</div>

# プロパティの追加

それでは、v-if を使用して、売り切れの商品を非表示にしましょう。

まず、"売り切れかどうか"という情報を、items の商品情報に soldOut というプロパティで持たせてみましょう。今回は id3 の商品を売り切れ状態にしてみます。id3 の商品に soldOut というプロパティを追加し、 true を設定します。






























 












<script setup>
import { ref } from 'vue'

const items = ref([
  {
    id: 1,
    name: 'アボカドディップバケット',
    description:
      '刻んだ野菜をアボカドと混ぜてディップに。こんがり焼いたバゲットとお召し上がりください。',
    price: 480,
    image: '/images/item1.jpg',
    soldOut: false
  },
  {
    id: 2,
    name: 'あの日夢見たホットケーキ',
    description:
      '子供のころに食べたかった、あのホットケーキを再現しました。素朴でどこか懐かしい味をどうぞ。',
    price: 1180,
    image: '/images/item2.jpg',
    soldOut: false
  },
  {
    id: 3,
    name: 'HOP WTR',
    description:
      'ロサンゼルス生まれのスパークリングウォーター。ノンカロリー、ノンアルコールの新感覚飲料です。',
    price: 320,
    image: '/images/item3.jpg',
    soldOut: true
  },
  {
    id: 4,
    name: 'チーズフレンチフライ',
    description:
      'イタリア産チーズをたっぷりかけたアツアツのフレンチフライ。みんな大好きな一品です。',
    price: 670,
    image: '/images/item4.jpg',
    soldOut: false
  }
])
</script>

# DOM 要素に v-if を追加

次に、DOM 要素に v-if を追加して、非表示にします。1 つ 1 つの商品を表示している要素は以下でハイライトしている部分です。

変更前












 
 
 
 
 
 
 
 
 
 
 
 



<template>
  <header class="header">
    <img
      src="/images/logo.svg"
      alt="">
    <h1>Vue.js ハンズオン</h1>
  </header>
  <main class="main">
    <template
      v-for="item in items"
      :key="item.id">
      <div class="item">
        <div class="thumbnail">
          <img
            :src="item.image"
            alt="">
        </div>
        <div class="description">
          <h2>{{ item.name }}</h2>
          <p>{{ item.description }}</p>
          <span>¥<span class="price">{{ item.price }}</span></span>
        </div>
      </div>
    </template>
  </main>
</template>

この <div> 要素に v-if を記述していきます。item.soldOuttrue の場合は、売り切れであることを示しています。

売り切れではない時、つまり item.soldOutfalse の時だけ表示をさせたいため、ひと工夫必要です。v-if="item.soldOut" としてしまうと、売り切れの場合のみ表示させることになってしまうため、! を使用して真偽値を逆転させて使用しましょう。

変更後












 
 
 
 
 
 
 
 
 
 
 
 
 
 



<template>
  <header class="header">
    <img
      src="/images/logo.svg"
      alt="">
    <h1>Vue.js ハンズオン</h1>
  </header>
  <main class="main">
    <template
      v-for="item in items"
      :key="item.id">
      <div
        v-if="!item.soldOut"
        class="item">
        <div class="thumbnail">
          <img
            :src="item.image"
            alt="">
        </div>
        <div class="description">
          <h2>{{ item.name }}</h2>
          <p>{{ item.description }}</p>
          <span>¥<span class="price">{{ item.price }}</span></span>
        </div>
      </div>
    </template>
  </main>
</template>

これで id3 の商品は非表示になりました。

ヒント

ここでは省略していますが、売り切れの状態を明示するため、id3 以外の商品は soldOut プロパティを false にしておくとよいでしょう。

# v-else や v-else-if の使い方

JavaScript の条件分岐の構文に else があるように、Vue.js にも同様のディレクティブが用意されています。else と同様の働きをするのが v-else です。

例えば、売り切れの場合は非表示にするのではなく"売り切れです"というメッセージを表示させたい場合は以下のように使用できます。

<div v-if="!item.soldOut">
  <!-- 省略 -->
</div>
<div v-else>売り切れです</div>

また、JavaScript の else if と同様の働きをする v-else-if も用意されています。v-if の評価が false の時に、さらに条件を指定したい時に使用できます。


+1 チャレンジ

ここまでの学習が完了した人は、以下の内容にも挑戦してみましょう。

# v-showとの違い

v-if に似た v-show というディレクティブが用意されています。以下のように、表示・非表示を制御したい DOM 要素に v-show を追加します。v-show の値が true の場合は表示され、 false の場合は表示されません。

<!-- 表示される -->
<div v-show="true">something</div>

<!-- 表示されない -->
<div v-show="false">something</div>

一見 v-if と同じように思えますが、v-if が DOM 要素ごと削除しているのに対して、v-show は style 属性の値に display:none; を付与して非表示にしています。

ブラウザ上での描画

<!-- 表示されない -->
<div style="display:none;">something</div>

ヒント

v-if は表示を切り替えるコストが高く、 v-show は初期描画のコストが高いです。そのため、頻繁に表示を切り替えるのであれば v-show を使い、それ以外では v-if を使うとよいでしょう。

ヒント

v-show<template> 要素に使えないことに気をつけましょう。また、 v-elsev-else-if も使えません。

# v-for との併用について

v-ifv-for を同時に使うことは推奨されていません。なぜなら、同じ要素において v-forv-if より優先度が高く v-if の評価に関わらず v-for の表示処理が行われるためです。以下の例のように、別の要素に分けることを推奨します。

<div v-if="!item.soldOut">
   <template
      v-for="item in items"
      :key="item.id">
      <div class="item">
      <!-- 省略 -->
      </div>
   </template>
</div>
<div v-else>売り切れです</div>