0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vueのv-showとv-ifは何が違うのか

0
Posted at

はじめに

この記事では、Vue の v-showv-if の違いを整理します。

どちらも「条件によって表示を切り替える」ための記法ですが、内部の動きは同じではありません。
見た目が似ているため、最初は「どちらでも同じでは」と感じやすいです。

ただし実際には、次の差があります。

  • v-if は要素や子コンポーネントを描画するかどうかを切り替える
  • v-show は要素を残したまま、表示だけを切り替える
  • そのため、向いている場面も少し違う

結論だけ先に言うと、頻繁に表示切り替えするなら v-show、そもそも出ないことが多いなら v-if から考えると整理しやすいです。

まず結論

違いを最短で整理すると次のとおりです。

項目 v-if v-show
非表示時 DOM に出さない DOM に残したまま display: none 相当で隠す
初回表示 条件が false なら描画しない 最初から描画する
切り替え時 作成・破棄が発生する 表示だけ切り替える
向いている場面 あまり表示が切り替わらない要素 頻繁に表示を切り替える要素
template で使えるか 使える 使えない

この表だけ覚えておけば、多くの場面では困りません。

v-if は条件に合うときだけ描画する

v-if は、条件に合うときだけその要素を描画します。
条件に合わなければ、その要素は最初から描画されません。

<script setup lang="ts">
import { ref } from "vue"

const isAdmin = ref(false)
</script>

<template>
  <p v-if="isAdmin">
    管理者メニュー
  </p>
</template>

この例では、isAdminfalse の間は p 要素自体が描画されません。

この動きのポイントは次のとおりです。

  • 初回表示で条件が false なら、そのブロックはまだ作られない
  • 条件が true になった時点で初めて描画される
  • 再び false になると、そのブロックは破棄される

Vue 公式でも、v-if は実際の conditional rendering であり、切り替え時にイベントリスナーや子コンポーネントが破棄・再作成される、と説明されています。

v-show は描画した上で見えなくする

v-show は、要素を描画したまま表示だけ切り替えます。

<script setup lang="ts">
import { ref } from "vue"

const isOpen = ref(false)
</script>

<template>
  <div v-show="isOpen">
    メニューの中身
  </div>
</template>

この場合、isOpenfalse でも div は描画されています。
ただし、表示だけが消えています。

実際には display: none 相当の形で非表示になります。

そのため、v-show のポイントは次のとおりです。

  • 最初から要素は作られる
  • 表示、非表示の切り替えは軽い
  • 要素自体は残る

ただし、初回表示では要素が最初から生成されるため、描画コストは v-if より高くなることがあります。

「今は見せないが、すぐまた出すかもしれない」ものにはこちらが向いています。

同じ見た目でも内部の意味は違う

画面だけ見ると、v-if でも v-show でも「消えている」ように見えます。
ただし、Vue にとっては意味がかなり違います。

たとえば、モーダル、開閉パネル、タブの中身のように何度も開いたり閉じたりする UI を考えます。

  • v-if は開くたびに作り、閉じるたびに消す
  • v-show は最初に作っておき、見せるか隠すかだけ切り替える

この差があるため、「頻繁に切り替えるなら v-show」という判断が出てきます。

逆に、管理者だけに見せる領域や、ある条件でしか一度も出ない重いブロックなら、v-if のほうが自然です。

どう使い分けるか

迷ったときは、次の基準で考えると整理しやすいです。

頻繁に開閉するなら v-show

例えば次のような UI です。

  • 開閉メニュー
  • アコーディオン
  • タブの切り替え
  • フィルター欄の表示、非表示

この種の UI は、表示の切り替えが多いです。
そのため、毎回作って消すより、最初から置いておいて見せ方だけ変える v-show が合いやすいです。

そもそも出ないことが多いなら v-if

例えば次のような UI です。

  • 権限があるユーザーにだけ見せる管理メニュー
  • エラー時だけ出す警告ブロック
  • データがあるときだけ出す詳細セクション

この種の UI は、初回表示で出ないことも多く、何度も切り替わらないこともあります。
その場合は v-if のほうが意図に合いやすいです。

template タグで使えるのは v-if

ここは地味ですが、実務ではよく効きます。

v-if<template> に付けられます。
複数要素をまとめて条件分岐したいときに便利です。

<template v-if="showDetail">
  <h2>詳細</h2>
  <p>説明文です。</p>
  <button>編集</button>
</template>

一方で v-show<template> には使えません。
v-show は実際に描画される要素の display を切り替える仕組みだからです。
template 自体は最終的に DOM に残らないため、v-show を適用する対象になりません。

複数要素をまとめて表示、非表示したい場合は、次のどちらかで考えることになります。

  • ラッパー要素に v-show を付ける
  • 本当に要素ごと出し分けたいなら v-if を使う

よくある誤解

v-show のほうが常に高性能というわけではない

v-show は切り替えコストが低いので便利です。
ただし、最初から描画はされます。

そのため、初回表示で不要な要素まで大量に持つ場合は、単純に v-show を増やせばよいわけではありません。

v-show は要素を DOM に残すため、初回レンダリング時の負荷が問題になるケースもあります。

見た目が同じでもライフサイクルは同じではない

v-if は子コンポーネントごと消えるため、内部 state やイベントリスナーの扱いにも影響します。
見た目だけで判断すると、あとで意図しない動きに見えることがあります。

迷ったらまずは意図で選ぶ

性能だけで決めるより、まず次の問いで選ぶほうが失敗しにくいです。

  • この要素は存在自体を切り替えたいのか
  • それとも存在はさせたまま見え方だけ変えたいのか

この問いに答えると、かなりの確率で v-ifv-show は自然に決まります。

まとめ

v-ifv-show は、どちらも条件付き表示のための記法です。
ただし、役割は同じではありません。

ポイントをまとめると次のとおりです。

  1. v-if は要素を描画するかどうかを切り替える
  2. v-show は要素を残したまま表示だけ切り替える
  3. 頻繁に切り替えるなら v-show が合いやすい
  4. そもそも出ないことが多いなら v-if が合いやすい
  5. 複数要素をまとめて切り替えたいときは template + v-if が使いやすい

Vue の条件分岐で迷ったら、まず「消したいのは表示だけか、要素そのものか」を考えると整理しやすくなります。

Vue のディレクティブ全体を俯瞰したい場合は Vueの主要ディレクティブをReactで書くとどうなるか でも整理しています。
テンプレート記法そのものの考え方については VueのテンプレートとReactのJSXは何が違うのか も関連します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?