前回はコンポーネントに外部からコンテンツを埋め込むことができるスロット(slot要素)を紹介しました。
前回の記事では、slot要素を使用して子コンポーネントに用意したコンテンツを差し込める場所に、親コンポーネントからテキストや任意のHTML要素を挿入しましたが、コンテンツを差し込める場所は1つしかありませんでした。
しかしコンポーネントを作成してれば、スロットによってコンテンツを埋め込む箇所を複数用意したい場合があります。
そこで今回は、1つのコンポーネント内に複数のスロットを用意して親コンポーネントからコンテンツを埋め込む方法について紹介します。
名前付きスロット
1つのコンポーネントに複数のスロットを用意する場合は、それぞれのスロットを判別するためのキーが必要になります。
そこでVue.jsのslot要素には、属性にname名前が指定できるようになっています。
名前付きスロットの書式
名前付きのslot要素を配置する場合は、以下のようにname属性で名前を指定します。
1 2 3 |
<slot name="スロットを判別するためのキーとなる名前"> ここにコンテンツを挿入する </slot> |
名前付きスロットの記述例
例えば以下のようなHTMLテンプレートがある場合
1 2 3 4 5 6 7 8 9 10 11 |
<div class="container"> <header> <!-- ここにヘッダーコンテンツを埋め込む --> </header> <main> <!-- ここにメインコンテンツを埋め込む --> </main> <footer> <!-- ここにフッターコンテンツを埋め込む --> </footer> </div> |
ヘッダー、メイン、フッターのそれぞれにスロット(slot要素)を配置し、各スロットに名前を付けると次のようになります。
1 2 3 4 5 6 7 8 9 10 11 |
<div> <header> <slot name="header"></slot> </header> <main> <slot name="main"></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> |
上記のHTMLテンプレートを持つ子コンポーネントを親コンポーネントから参照する場合は以下のようにします。(ここではコンポーネントの名前を「container-component」とします。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div id="app"> <container-component> <template v-slot:header> <h1>タイトル</h1> </template> <template v-slot:main> <p>メインコンテンツ1</p> <p>メインコンテンツ2</p> <p>メインコンテンツ3</p> </template> <template v-slot:footer> <div> <p>コピーライト</p> </div> </template> </container-component> </div> |
親コンポーネントから子コンポーネントの名前付きスロットにコンテンツを挿入する時は、v-slotディレクティブを使用します。(3行目、7行目、13行目)
ここでは、ヘッダー、メイン、フッターのそれぞれにtemplate要素を配置して、「header」「main」「footer」の名前を付けたスロットにv-slotディレクティブを指定しています。
名前付きスロットを利用する場合は「template要素を配置してv-slotディレクティブで名前を指定」します。
v-slotディレクティブには「v-slot:名前」の形式で引数に名前を指定します。
上記のコードを実行すると、以下のHTMLが出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<div> <header> <h1>タイトル</h1> </header> <main> <p>メインコンテンツ1</p> <p>メインコンテンツ2</p> <p>メインコンテンツ3</p> </main> <footer> <div> <p>コピーライト</p> </div> </footer> </div> |
表示される画面は以下のようになります。
上記の例では、すべてのスロットにname属性で名前を付けていますが、name属性は省略することもできます。
name属性を持たないslot要素は、暗黙的に「default」という名前と見なされます。
例えば、上記のmain要素のname属性を省略して以下のようにすると
1 2 3 4 5 6 7 8 9 10 11 |
<div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> |
親コンポーネントのHTMLテンプレートは以下のようにv-slotディレクティブの引数の名前に「default」を指定することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<container-component> <template v-slot:header> <h1>タイトル</h1> </template> <template v-slot:default> <p>メインコンテンツ1</p> <p>メインコンテンツ2</p> <p>メインコンテンツ3</p> </template> <template v-slot:footer> <div> <p>コピーライト</p> </div> </template> </container-component> </div> |
名前を省略したスロットがある場合は、v-slotディレクティブでバインドせずに以下のようにコンテンツを配置すると、名前がスロットにコンテンツが挿入されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<container-component> <template v-slot:header> <h1>タイトル</h1> </template> <p>メインコンテンツ1</p> <p>メインコンテンツ2</p> <p>メインコンテンツ3</p> <template v-slot:footer> <div> <p>コピーライト</p> </div> </template> </container-component> |
上記の例では、メインコンテンツをヘッダーとフッターの間に配置していますが、名前が省略されているスロットに埋め込むコンテンツは以下のようにどこに配置しても挿入されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<container-component> <p>メインコンテンツ1</p> <template v-slot:header> <h1>タイトル</h1> </template> <template v-slot:footer> <div> <p>コピーライト</p> </div> </template> <p>メインコンテンツ2</p> <p>メインコンテンツ3</p> </container-component> |
v-slotディレクティブの省略記法
v-slotディレクティブには、v-bindディレクティブやv-onディレクティブと同様に省略記法が用意されています。
v-slotディレクティブの省略記法は「#」になります。「v-slot:」の部分を「#」に置き換えることができます。
1 |
<template #name >...</template> |
ディレクティブの省略記法については、以下の記事も参考にしてください。
v-slotディレクティブの動的引数
v-slotディレクティブでは、v-bindディレクティブやv-onディレクティブと同様に動的引数を利用する事ができます。
1 |
<template v-slot:[name] >...</template> |
ディレクティブの動的引数については、以下の記事も参考にしてください。