今回は、Vue.jsのディレクティブと呼ばれるものを紹介したいと思います。ディレクティブはVue.jsが持つ強力な機能の1つです。Vue.jsを使いこなすためには、ディレクティブを使いこなすことが必要になります。今回の記事では、「Vue.jsのディレクティブとは?」、「ディレクティブをどうやって使うのか?」、「ディレクティブにはどんなものがあり、どれを使えばいいのか?」といった疑問を解消できるように、サンプルコードを交えながら説明していきたいと思います。
ディレクティブの全てを1つの記事すると記述量が膨大になるため、何回かに分けて記事にしたいと思います。 前提としてこの記事では、Vue3での記法を前提とします。
- ディレクティブについて理解する。
- v-ifについて理解する。
- v-showについて理解する。
- v-ifとv-showの使い分けを理解する
ディレクティブとは?
ディレクティブは「Vue.js対して特定の指示や設定を行うための命令」です。HTMLタグにv-で始まる特別な属性を書き加えることで、Vue.jsはその要素に対して特定の動的な振る舞いを適用します 。
<p v-if="seen">Now you see me</p>
上記の「v-if」がディレクティブです。これは、Vueに対してseenというデータの値がtrueの時だけ、このタグ(
タグ)を表示するという指示になります。seenの値が変わると、Vueは自動的にDOMを更新し、要素を表示したり、消したりします。
「v-」から始まる理由
接頭語に「v-」つけることで、Vueが提供する属性ある事を明確に示すことができます。これは、開発者目線だけでなく、Vueの内部処理としても効率的にディレクティブを見つけて処理をすることができます。
v-if:条件を指定する要素
「v-if」は条件付きディレクティブになります。指定された値の真偽値(true/false)に基づいて、要素をレンダリングします。falseの場合は、ブラウザに表示されるDOMから完全に要素を取り除きます。
v-ifの基本的な使い方
<script setup> import { ref } from 'vue' const isVisible = ref(true) </script> <template> <button @click="isVisible = !isVisible">表示/非表示を切り替え</button> <h1 v-if="isVisible">Vueは素晴らしい!</h1> </template>
このコードでは、isVisibleというデータを定義し、初期値をtrueにしています。v-ifの特徴の一つに、「遅延描画(lazy rendering)」という性質があります 。もし最初のページ読み込み時にv-ifの条件がfalseだった場合、Vueはその要素をレンダリングするための処理を一切行いません。 今回で言うと、isVisibleの値がfalseであった場合に、初期表示にその要素のレンダリングが行われません。
isVisible=falseとして、初期表示を行った場合、以下のページの赤枠のように本来表示される個所に何も出力がされていません。

これは、リソースの節約になり、ページの初期表示が速くなるというメリットがあります。
v-else と v-else-ifを使った条件分岐
Vue.jsには、「v-else」と「v-else-if」ディレクティブが用意されています 。プログラムをされた方であれば、イメージがつくかと思うのですが、if...elseやif...else if...elseと同じような複雑な条件分岐をするためのディレクティブです。
「v-else」と「v-else-if」ディレクティブを使う際に注意すべきことがあります。それは、「v-else」と「v-else-if」の要素は、必ず「v-if」または「v-else-if」の要素の直後に配置しなければならない、という点です 。間に他の要素が入ってしまうと、Vueは関連性を認識できず、正しく動作しません。
v-else と v-else-ifの基本的な使い方
<script setup> import { ref } from 'vue' const score = ref(40) // この値を変えてみてください </script> <template> <div v-if="score >= 80">大変よくできました!</div> <div v-else-if="score >= 60">よくできました!</div> <div v-else-if="score >= 40">もう少し頑張りましょう。</div> <div v-else>追試です。</div> </template>
この例では、scoreの値に応じて、いずれか一つのdiv要素だけが表示されます。
templateタグを使った複数の要素をまとめた条件分岐
「見出しと段落と画像を、全部まとめて同じ条件で表示・非表示したい!」というケースもよくあります。そんな時、それぞれの要素に同じv-ifを書いていくのは冗長ですし、コードの見通しも悪くなります。そんな時に役に立つのが「template」タグです。 「template」タグは、レンダリングされないラッパーとして機能します。このタグに「v-if」などのディレクティブを付けると、その中に含まれるすべての要素に条件が適用されます。そして、最終的にブラウザに表示されるHTMLには、「template」タグ自体は残りません。
templateタグを使った上家分岐の基本的な使い方
<script setup> import { ref } from 'vue' const ok = ref(false) </script> <template> <template v-if="ok"> <h2>タイトル</h2> <p>段落1</p> <p>段落2</p> </template> </template>
このコードでは、okがtrueの時にh1と2つのpタグがまとめて表示され、falseの時にはすべてがDOMから削除されます。「template」タグのおかげで、コードがすっきりとまとまり、管理しやすくなりますね。もちろん、この「template」タグには「v-else」や「v-else-if」も使えます 。
v-ifの本質:構造的かつライフサイクルを意識したディレクティブ
「v-if」は単に要素を隠すだけではありません。要素を「破棄」し、必要になったら「再生成」します。これが何を意味するかというと、「v-if」ブロック内のVueコンポーネントは、その表示・非表示が切り替わるたびに、ライフサイクル全体を経験するということです。
つまり、「v-if」の条件がfalseになるとコンポーネントはunmounted(破棄)され、trueになると新しいインスタンスとしてcreatedされmounted(生成・配置)されます。これは、コンポーネントの内部状態(例えば、ユーザーが入力したテキストなど)がリセットされることを意味します。また、mountedフックでデータの取得などを行っている場合、表示されるたびにその処理が再実行されます。
このように、「v-if」は単なる表示切り替えツールではなく、アプリケーションの一部を動的に生成・破棄するための、ライフサイクルに深く関わる構造的なディレクティブなのです。
v-showを使った表示の切り替え
条件によって表示を切り替えるディレクティブには、もう一つ「v-show」という選択肢があります 。「v-if」と使い方は似ていますが、内部的な仕組みは全く異なります。「v-show」の仕組みは、条件の真偽値(true/false)に関わらず、常に要素をレンダリングし続けることにあります。条件がfalseの場合は、「v-if」とは異なり、要素を削除するのではなく、CSSのdisplay: none;というスタイルを適用して、見た目上、見えなくするだけです。
v-showの基本的な使い方
<script setup> import { ref } from 'vue' const isVisible = ref(true) </script> <template> <button @click="isVisible =!isVisible">表示/非表示を切り替え</button> <h1 v-show="isVisible">こんにちは!</h1> </template>
ボタンを押したときの挙動は「v-if」の例と全く同じに見えます。しかし、ブラウザの開発者ツールでHTMLの構造を覗いてみると、isVisibleがfalseのとき、h1タグにstyle="display: none;"が付与されているのが確認できます。

v-showを使う時の注意点
「v-show」は。「v-else」や「v-else-if」と連携して使うことはできません。また、後述する「template」タグにも対応していません 。
v-showの本質:状態を保持するディレクティブ
「v-show」がCSSで表示を切り替えるだけ、ということは、その要素(またはコンポーネント)のインスタンスは一度レンダリングされたらずっと破棄されません。これは、要素の内部状態が常に保持されることを意味します。
例えば、「v-show」で管理されているフォームの入力欄にユーザーが何かを書き込んだとします。そのフォームを一度非表示にしてから再度表示しても、入力した内容はそのまま残っています。もし同じことを「v-if」で行うと、要素が再生成されるため入力内容は消えてしまいます。このように、ユーザーの入力やコンポーネントの状態を維持したい場合には「v-show」が非常に有効です。
v-ifとv-showの使い分け
「v-if」と「v-show」はどちらも要素の表示を変える際に利用でき、似たような振る舞いをします。そうなると、どちらを使えばよいのか?と迷うことがあります。これは、状況に応じて最適な方を選ぶ必要があるため、その判断基準を持っておくことが重要です。
パフォーマンスのトレードオフ
v-if:
- 表示を切り替えるたびにDOM要素の生成と破棄という重い処理が走るため、「切り替えコスト」が高いです。
- 初期表示時に条件がfalseなら何も描画しないため、「初期描画コスト」は低いです。
v-show:
- 切り替えはCSSのプロパティを変更するだけなので非常に高速で、「切り替えコスト」は低いです。
- 常にDOMに要素を描画しておく必要があるため、「初期描画コスト」は高いです。
振る舞いの違い(状態の保持)
v-if:
- 要素が一度破棄されるため、その要素(や内部のコンポーネント)が持っていた内部的な状態(例えば、フォームに入力されたテキストなど)はリセットされます。再度表示されるときには、全く新しい「まっさら」な状態で生成されます。これは、毎回リセットしたいモーダルウィンドウなどでは都合が良い振る舞いです。
v-show:
- 要素は破棄されず、ずっと存在し続けるため、非表示になっても内部の状態は保持されます。ユーザーが入力した内容などを維持したまま、表示・非表示を切り替えたい場合に適しています。
使い分けの指針
これらの特性を踏まえると、以下のような使い分けが推奨されます。
v-ifを使うべき時:
- 条件が実行時に頻繁には変わらない場合
- 表示されるたびに、コンポーネントを初期状態から作り直したい場合。
- 例:ユーザーの権限やログイン状態によって表示する管理メニュー・ボタンなど
v-showを使うべき時:
- 条件が非常に頻繁に切り替わる場合(例:タブの切り替えなど)。
- 要素の状態を維持したまま、表示・非表示を高速に切り替えたい場合。
- 例:タブの切り替え、アコーディオンメニュー、頻繁に表示されるモーダルダイアログなど
これらの内容のまとめとして、一目で違いがわかるように、以下の比較表にまとめてみました。
| 特徴 | v-if | v-show |
|---|---|---|
| 仕組み | DOM要素を直接追加・削除 | CSSのdisplayプロパティを切り替え |
| 初期描画コスト | 低い(条件がfalseの場合) | 高い(常に描画される) |
| 切り替えコスト | 高い(DOMの再構築が発生) | 低い(CSSの変更のみ) |
| 状態の保持 | 破棄される | 保持される |
| v-else / v-else-if | 連携可能 | 連携不可 |
| おすすめの使い所 | 条件が頻繁に変わらない場合 | 条件が頻繁に変わる場合 |
まとめ
今回はVue.jsディレクティブの基本と、条件付きレンダリングの「v-if」と「v-show」についてまとめました。この2つは似ている動きをしますが、しっかりと内容や仕組みを理解して利用していきたいですね。今回の記事がVue.jsを使う方の参考になれば幸いです。