はじめに
はじめまして、学生エンジニアの@huyunokiです。
Vue.jsで要素の表示・非表示を切り替えるとき、v-if と v-show という2つの主要なディレクティブがあります。どちらも同じように見えますが、内部的な動作とパフォーマンスへの影響は全く異なります。
この記事ではこの2つのディレクティブの決定的な違いを明確にし、最適化するための正しい使い分け方を解説します。
1. v-if (完全に要素を破棄/生成する)
v-if は条件が false の場合、その要素とその内部のコンポーネントをDOMから完全に削除します。条件が true になると、ゼロから要素を再構築(マウント)します。
動作のイメージ
- 条件が
falseのとき:DOMツリーに存在しない - 条件が
trueのとき:DOMツリーに存在する
v-ifの特徴
| 特徴 | 詳細 |
|---|---|
| レンダリング | 遅い。条件が変わるたびに要素全体を破棄・再生成するため、コストが高い。 |
| トグルコスト | 高い。要素の破棄と生成はCPU負荷が高い。 |
| 表示コスト | 低い。DOMに存在しないため、メモリ消費は抑えられる。 |
| 用途 | めったに表示/非表示が切り替わらない要素(例:認証後の設定パネル、ページ全体のレイアウト切り替えなど) |
連携ディレクティブ
v-if には条件に応じた排他的な表示を可能にする以下のディレクティブが連携できます。
| ディレクティブ | 役割 | 構文 |
|---|---|---|
v-if |
条件が true の場合のみ要素を表示。 |
<div v-if="isLoggedIn">ようこそ</div> |
v-else-if |
前の条件が false の場合に、次の条件をチェックする。 |
<div v-else-if="isAdmin">管理者メニュー</div> |
v-else |
すべての条件が false だった場合に表示される。 |
<div v-else>ログインしてください</div> |
テンプレート (<template>)
<!-- 条件によってDOMから要素が削除・生成される -->
<div v-if="userType === 'admin'">管理者パネル</div>
<div v-else-if="userType === 'editor'">編集者パネル</div>
<div v-else>一般ユーザー</div>
2. v-show (CSSで表示/非表示を切り替える)
v-show は条件が false の場合でも、その要素をDOMに保持し続けます。表示/非表示は、要素の display CSSプロパティ(display: none;)を切り替えることで制御されます。
動作のイメージ
- 条件が
falseのとき:DOMツリーに存在する(style="display: none;") - 条件が
trueのとき:DOMツリーに存在する(style属性なし)
v-showの特徴
| 特徴 | 詳細 |
|---|---|
| レンダリング | 速い。初期ロード時または親がマウントされた時に一度だけ描画される。 |
| トグルコスト | 低い。単にCSS属性を切り替えるだけなので、非常に高速。 |
| 表示コスト | 高い。常にDOMに存在するため、初期ロード時間やメモリ消費が増える。 |
| 用途 | 頻繁に表示/非表示が切り替わる要素(例:モーダルウィンドウ、タブ切り替え、ツールチップなど) |
テンプレート (<template>)
<!-- CSSプロパティ(display: none;)の切り替えのみが行われる -->
<div v-show="isModalOpen">モーダルコンテンツ</div>
3. 正しい使い分けの決定版
どちらを使うべきかを判断するための明確な基準は、「切り替えの頻度」と「初期ロードのコスト」です。
| 質問 | 答え | 選択すべきディレクティブ | 理由 |
|---|---|---|---|
| 表示/非表示の切り替えは頻繁か? | YES(例: 0.5秒ごとに切り替わる) | v-show |
トグルコストが低く、非常に速い。 |
| 表示/非表示の切り替えは頻繁か? | NO(例: ユーザーがログインしたときだけ) | v-if |
初期構築コストは高いが、不要な要素をDOMから削除できる。 |
| 初期ロード時に非表示のままか? | YES(常に隠れているモーダルなど) | v-show |
初期表示が速く、すぐに切り替わる準備ができている。 |
| 要素の描画コストは高いか? | YES(複雑なグラフや大規模なデータテーブルなど) | v-if |
不要なときはDOMから削除し、メモリ使用量を抑える。 |
まとめ:
-
デフォルトは
v-ifを使う(不要な要素をDOMから排除するため)。 -
トグルが頻繁に必要な場合のみ
v-showに切り替える。