・Vue.jsのslotはどう使う?
こんな疑問にお答えします。
親→子コンポーネントにデータを渡すにはpropsを使いますよね。
ただ場合によってはタグなどコンテンツごと渡したい場合があるかと。
そこで使えるのが「slot」です。
今回は自分用のメモとして「slot」についてまとめてみました!
参考にどうぞ
ということで、この記事では「Vue.jsのslotの使い方」について解説していきます!
・slotの基本的な使い方
・slotのフォールバックコンテンツ
・slotの名前付きスロット
・slotのスコープ付きスロット
目次
【解説】Vue.jsのslotの基本的な使い方
実際に「v-slot」を使ってみたサンプルがこちら↓
<script setup lang="ts">
import TestSlot from './components/TestSlot.vue'
</script>
<template>
<TestSlot>
<h2>スロットで表示</h2>
<p>ここにスロット用の文章が入ります</p>
</TestSlot>
</template>
<template>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<slot/>
</template>
親で記述したコンテンツが、子コンポーネントに渡されて表示されるようになります。
slotの使い方で重要な点がこちら↓
①親:コンポーネントの閉じタグを記述
②親:その中に渡したいコンテンツを入れる
③子:「v-slot」を記述
順に解説してきます。
まず親ファイルにて、読み込むコンポーネントタグに閉じタグを記述します。
<template>
<TestSlot></TestSlot>
</template>
次にそのコンポーネントタグの中に、渡したいコンテンツを記述しましょう。
<template>
<TestSlot>
<!-- 渡したいコンテンツを記述 -->
<h2>スロットで表示</h2>
<p>ここにスロット用の文章が入ります</p>
<!-- 渡したいコンテンツを記述 -->
</TestSlot>
</template>
今回は例としてh2タグやpタグらを入れました。
あとは子ファイルにて、渡されたコンテンツを表示すればOK。
やり方は「slot」タグを記述するだけです。
<template>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<slot/>
</template>
これで「slot」タグを記述した部分に、親で書いたコンポーネントタグ内のコンテンツが表示されます。
基本的な使い方はこの通りとなります!
【解説】Vue.jsのslotのフォールバックコンテンツ
実はslotはデフォルトのコンテンツを用意しておく機能があります。
ようは親ファイルのコンポーネントタグ内に何も記述されてなかったときに、表示する用のコンテンツですね。
それがフォールバックコンテンツです。
そんなフォールバックコンテンツのサンプルがこちら↓
<script setup lang="ts">
import TestSlot from './components/TestSlot.vue'
</script>
<template>
<TestSlot />
</template>
<template>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<p>ここに文章が入ります</p>
<slot>
<h2>デフォルトのスロット</h2>
<p>何もコンテンツが渡されない場合の文章</p>
</slot>
</template>
デフォルト用のコンテンツが表示されます。
フォールバックコンテンツのやり方は簡単で、「slot」の閉じタグを書き、その中にデフォルト用のコンテンツを記述するだけです。
<slot>
<h2>デフォルトのスロット</h2>
<p>何もコンテンツが渡されない場合の文章</p>
</slot>
これで下記のようにコンポーネントタグ内に何も書かれていなかったら、先ほどのデフォルト内容が表示されるということです。
<template>
<TestSlot />
</template>
【解説】Vue.jsの名前付きスロットの使い方
「slot」を複数使い、それぞれ特定の部分に表示させたいときもありますよね。
実はそんなときに使える「名前付きスロット」というものがあります。
そのサンプルがこちら↓
<script setup lang="ts">
import TestSlot from './components/TestSlot.vue'
</script>
<template>
<TestSlot>
<template v-slot:header>
<h1>ヘッダー用タイトル</h1>
</template>
<template v-slot:item01>
<h2>メイン用タイトル</h2>
</template>
<template v-slot:footer>
<p>フッター用文章です</p>
</template>
</TestSlot>
</template>
<template>
<header>
<slot name="header"/>
<p>①ここに文章が入ります</p>
</header>
<main>
<slot name="item01"/>
<p>②ここに文章が入ります</p>
</main>
<footer>
<slot name="footer"/>
<p>③ここに文章が入ります</p>
</footer>
</template>
「slot」につけたnameの値に合わせて、それぞれの部分に表示されます。
名前付きスロットの使い方で重要なのがこちら↓
⓪子:「slot」タグを複数用意
①子:「slot」タグのname属性に識別子を入れる
②親:「template」タグをコンポーネントタグ内に記述
③親:「template」タグに「v-slot:識別子」と記述
順に見ていきましょう。
まず前提としてわかりやすいように、「slot」タグを複数用意しておきます。
<template>
<header>
<slot/>
<p>①ここに文章が入ります</p>
</header>
<main>
<slot/>
<p>②ここに文章が入ります</p>
</main>
<footer>
<slot/>
<p>③ここに文章が入ります</p>
</footer>
</template>
headerタグ内、mainタグ内、footerタグ内に1つずつ記述しました。
特定の「slot」タグ部分に、親で指定した特定のコンテンツを入れるのがゴールです。
そのために「slot」タグにname属性を記述して、任意の識別子を記述します。
<template>
<header>
<slot name="header"/>
<p>①ここに文章が入ります</p>
</header>
<main>
<slot name="item01"/>
<p>②ここに文章が入ります</p>
</main>
<footer>
<slot name="footer"/>
<p>③ここに文章が入ります</p>
</footer>
</template>
今回は例として「header」「item01」「footer」という識別子を入れました。
続いて親ファイルにて、複数の「template」タグを用意します。
<template>
<TestSlot>
<!-- name="header"に入れたいコンテンツ -->
<template>
<h1>ヘッダー用タイトル</h1>
</template>
<!-- name="item01"に入れたいコンテンツ -->
<template>
<h2>メイン用タイトル</h2>
</template>
<!-- name="footer"に入れたいコンテンツ -->
<template>
<p>フッター用文章です</p>
</template>
</TestSlot>
</template>
この「template」タグが、先述したslotタグに表示させる役割となります。
そしたら用意した「template」タグに「v-slot:識別子」を記述しましょう。
この識別子には、子のnameの値に書いたものを入れます。
<template>
<TestSlot>
<!-- name="header"に入れたいコンテンツ -->
<template v-slot:header>
<h1>ヘッダー用タイトル</h1>
</template>
<!-- name="item01"に入れたいコンテンツ -->
<template v-slot:item01>
<h2>メイン用タイトル</h2>
</template>
<!-- name="footer"に入れたいコンテンツ -->
<template v-slot:footer>
<p>フッター用文章です</p>
</template>
</TestSlot>
</template>
先ほど用意した識別子に合わせて「v-slot:header」「v-slot:item01」「v-slot:footer」と記述しました。
「v-slot:header」内のコンテンツ→「slot name=”header”」部分で表示
「v-slot:item01」内のコンテンツ→「slot name=”item01″」部分で表示
「v-slot:footer」内のコンテンツ→「slot name=”footer”」部分で表示
このように書くことで、子コンポーネントの特定のslotタグ部分に表示させることができます。
これが名前付きスロットの基本的な使い方です。
ちなみに「v-slot:識別子」は省略して書くことが可能です。
それが「#識別子」という書き方です。
<template>
<TestSlot>
<!-- name="header"に入れたいコンテンツ -->
<template #header>
<h1>ヘッダー用タイトル</h1>
</template>
<!-- name="item01"に入れたいコンテンツ -->
<template #item01>
<h2>メイン用タイトル</h2>
</template>
<!-- name="footer"に入れたいコンテンツ -->
<template #footer>
<p>フッター用文章です</p>
</template>
</TestSlot>
</template>
この書き方でも実装可能です。
ちなみに名前付きスロットでも、フォールバックコンテンツを使うことは可能です。
下記のような場合、slotタグ内のデフォルトコンテンツが表示されます。
<!-- v-slot付きtemplateタグ内にコンテンツがない場合 -->
<template v-slot:item01></template>
<!-- v-slot付きtemplateタグ自体がない場合 -->
<!-- <template #item01></template> -->
<slot name="item01">
なにもない場合この文章が入ります。
</slot>
豆知識ですがname属性に何も指定してないslotタグは、「name=”default”」がついているのと同じ意味になります。
<!-- 同じ意味になる -->
<slot/>
↓
<slot name="default"/>
そのため下記の様に書いたら、上記のslotタグ部分に表示されます。
<template v-slot:default>
<h2>デフォルト用タイトル</h2>
</template>
【解説】Vue.jsのスコープ付きスロットの使い方
実はスロット内でプロパティを渡して、親コンポーネントで受け取る方法機能があります。
それが「スコープ付きスロット」です。
これを使えばスロットごとにカスタマイズ等ができます。
そのサンプルがこちら↓
<script setup lang="ts">
import TestSlot from './components/TestSlot.vue'
</script>
<template>
<TestSlot>
<template #item01="slotProps">
<p>{{ slotProps.numtext }}は「{{ slotProps.count }}」です</p>
</template>
</TestSlot>
</template>
<script setup>
import { ref } from 'vue';
const num = ref(0);
</script>
<template>
<button @click="num++">クリック</button>
<slot name="item01" :count="num" numtext="今の数値" />
</template>
「今の数値」というテキスト+クリック毎に増える数値は、プロパティを渡して表示しています。
スコープ付きスロットの使い方手順がこちら↓
①子:slotタグに属性と値を記述
②親:#識別子の値に変数名を記述
③親:その変数名を使いデータを表示
※:デフォルトの場合
順に解説してきます。
まず子ファイルのslotタグに対して、属性と渡したいデータの値を記述します。
今回は例として「num」という動的な値と、「今の数値」という静的なテキストを記述しました。
<slot name="item01" :count="num" numtext="今の数値" />
バインディングするデータを使いたいときは「:」を属性につけます。
続いて名前付きスロットで用いた「v-slot:識別子」もしくは「#識別子」に値をつけます。
その値に任意の変数名を記述しましょう。
<template #item01="slotProps">
</template>
一般的には「slotProps」とつけることが多いそう。
後はその変数名を使って、渡されたデータを表示すればOKです。
実はこの変数名はオブジェクトになってくれるため、プロパティを指定すれば表示可能です。
「slotProps.numtext」や「slotProps.count」の感じですね。
<template #item01="slotProps">
<p>{{ slotProps.numtext }}は「{{ slotProps.count }}」です</p>
</template>
これで渡されたデータが表示できます。
ちなみにこのスコープ付きスロットは、名前付きのtemplateタグの中でのみ使うことができますよ。
補足ですが#defaultのスロットは、templateタグで囲まないとスコープ付きスロットを使うことができません。
そのため下記の「template #default=”slotProps”」のように記述しましょう。
<template>
<button @click="num++">クリック</button>
<slot :count="num" numtext="今の数値" />
</template>
<template>
<TestSlot>
<!-- 使えない -->
<p>{{ slotProps.numtext }}は「{{ slotProps.count }}」です</p>
<!-- 使える -->
<template #default="slotProps">
<p>{{ slotProps.numtext }}は「{{ slotProps.count }}」です</p>
</template>
</TestSlot>
</template>
名前付きスロットが一個もない場合は、コンポーネントタグに対して「v-slot=”変数名”」を記述することが可能です。
<template>
<TestSlot v-slot="slotProps">
<p>{{ slotProps.numtext }}は「{{ slotProps.count }}」です</p>
</TestSlot>
</template>
<template>
<button @click="num++">クリック</button>
<slot :count="num" numtext="今の数値" />
</template>
【解説】Vue.jsのslotの使い方【名前付き/スコープ付き】 :まとめ
- スロットを使えばタグごとデータを渡すことが可能
- デフォルト用のコンテンツを用意が可能(フォールバックコンテンツ)
- 名前付きスロットを使えば特定部分に表示可能
- スコープ付きスロットを使えばプロパティの値を渡すことが可能
Vue.jsのslotを使う時はためしてみてね!