VueJS 速習チュートリアル

Vue v-slot

名前付きスロット(Named Slots)を参照するには、v-slot ディレクティブが必要です。
名前付きスロットを使用すると、子コンポーネントのテンプレート内のどこにコンテンツを配置するかを、より詳細に制御できるようになります。
これにより、より柔軟で再利用性の高いコンポーネントを作成することが可能になります。

名前付きスロットや v-slot を使う前に、まずコンポーネント内で2つのスロットをそのまま使用するとどうなるかを見てみましょう。

1. 実装例(名前なしスロットを複数使った場合)

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp>'Hello!'</slot-comp>

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot></slot>
</div>
<div>
  <slot></slot>
</div>

コンポーネント内に2つのスロットがある場合、コンテンツが両方の場所にそのまま表示されることがわかります。

2. v-slot と名前付きスロット

コンポーネント内に複数の <slot> があり、かつ特定のコンテンツを特定の <slot> に表示させたい場合は、各スロットに名前を付け、v-slot を使って正しい場所へコンテンツを送り出す必要があります。

2.1 実装例

スロットを区別するために、それぞれに異なる名前を付けます。

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot name="topSlot"></slot>
</div>
<div>
  <slot name="bottomSlot"></slot>
</div>

これで、App.vue 側で v-slot を使用して、コンテンツを適切なスロットに向けることができます。

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp v-slot:bottomSlot>'Hello!'</slot-comp>

3. デフォルトスロット(Default Slots)

名前(name 属性)のない <slot> は、v-slot:default とマークされたコンテンツ、または v-slot でマークされていないコンテンツを受け取るためのデフォルト(Default)スロットになります。

これがどのように動作するか、前述の例に少し変更を加えて確認してみましょう。

3.1 実装例

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot></slot>
</div>
<div>
  <slot name="bottomSlot"></slot>
</div>

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp v-slot:bottomSlot>'Hello!'</slot-comp>

前述の通り、明示的に v-slot:default と記述することで、そのコンテンツがデフォルトスロットに属することをより明確にすることもできます。

3.2 デフォルトスロットの明示的な指定

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot></slot>
</div>
<div>
  <slot name="bottomSlot"></slot>
</div>

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp v-slot:default>'デフォルトスロットへのコンテンツ'</slot-comp>

4.  内での v-slot

これまで見てきたように、v-slot ディレクティブはコンポーネントタグの属性として使用できます。
また、複数の要素を含む大きなコンテンツの塊を特定の <slot> に送るために、<template> タグ内で v-slot を使用することもできます。

4.1 実装例

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp>
  <template v-slot:bottomSlot>
    <h4>下のスロットへ!</h4>
    <p>この p タグと上の h4 タグは、template タグで使用された v-slot ディレクティブによって bottomSlot へ送られます。</p>
  </template>
  <p>これはデフォルトスロットに入ります</p>
</slot-comp>

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot></slot>
</div>
<div>
  <slot name="bottomSlot"></slot>
</div>

特定の <slot> にコンテンツを振り分けるために <template> タグを使用するのは、<template> 自体はレンダリングされず、単なるコンテンツのプレースホルダとして機能するからです。ビルドされたページをブラウザのインスペクタで確認しても、template タグ自体は見当たりません。

5. v-slot の省略記法(#)

v-slot: のショートハンド(省略記法)は # です。

つまり、次のような記述:
<slot-comp v-slot:topSlot>'Hello!'</slot-comp>

は、このように書き換えることができます:
<slot-comp #topSlot>'Hello!'</slot-comp>

5.1 実装例

App.vue:

<h1>App.vue</h1>
<p>コンポーネントには、それぞれに1つのスロットを持つ2つの div タグがあります。</p>
<slot-comp #topSlot>'Hello!'</slot-comp>

SlotComp.vue:

<h3>コンポーネント</h3>
<div>
  <slot name="topSlot"></slot>
</div>
<div>
  <slot name="bottomSlot"></slot>
</div>