などの疑問や悩みを解決してまいります。
Vue.jsにおけるslot
機能はとても便利なものですが、初心者が最初に扱う場合ややこしくてこんがらがってしまうことも多いかと思います。
今回は初心者の方に向けて分かりやすいようにslot
について解説していきます。
slotとは
slot
とは親コンポーネントから子コンポーネントにコンテンツを挿入することができる機能です。
親コンポーネントから子コンポーネントに値を渡すProps
に似ていますが、Props
はデータを、slot
はコンテンツを挿入するという違いがあります。
slotを使ったコード例紹介
それでは実際にslot
を簡単なコードで使用してみます。
親コンポーネントにApp.vue、子コンポーネントにSlotContent.vueを用意しました。
<script setup lang="ts">
import SlotContent from './components/SlotContent.vue';
</script>
<template>
<SlotContent>
<!-- slotタグ内に入るコンテンツ -->
<div class="content">
<h1>slotの使い方について</h1>
<p>初心者の方にもわかりやすく解説します。</p>
</div>
<!-- /slotタグ内に入るコンテンツ -->
</SlotContent>
</template>
<template>
<p>↓親コンポーネントのコンテンツの内容がslotタグ内に入ります。↓</p>
<slot></slot>
</template>
表示結果は以下のようになります。
コンポーネントタグ内のHTMLコンテンツが挿入される
わかりやすくコメントも記述していますが、子コンポーネントのSlotContent
タグ内に記述されているHTMLコンテンツ(content
クラス)が、子コンポーネントのslotタグ内に挿入されたことが分かるかと思います。
<!-- slotタグ内に入るコンテンツ -->
<div class="content">
<h1>slotの使い方について</h1>
<p>初心者の方にもわかりやすく解説します。</p>
</div>
上記のコードが、
<slot></slot>
slot
タグ内に挿入されました。
複数箇所に表示させる場合
1か所だけではなく複数箇所にHTMLコンテンツを反映させることも可能です。
空のslot
タグをテキストの上にもう1つ配置してみてください。
するとテキストの上にも同様のコンテンツが表示されたかと思います。
デフォルト(フォールバックコンテンツ)の指定
先の解説では、SlotContent
タグ内にあったHTMLコンテンツを子コンポーネントの空のslot
タグ内に挿入することができましたが、slot
タグ内に内容を記述すると、SlotContent
タグ内のコンテンツが何もないとき(空タグのとき)にフォールバックコンテンツを指定することができます。
<template>
<!-- デフォルトの内容が入ります -->
<SlotContent />
<SlotContent>
<div class="content">
<h1>slotの使い方について</h1>
<p>初心者の方にもわかりやすく解説します。</p>
</div>
</SlotContent>
</template>
<template>
<slot>デフォルトの値が表示されます。</slot>
</template>
このように、先程とは異なりslot
タグ内にテキストを追加しました。
親コンポーネント側はSlotContent
タグ内にコンテンツがないものを別に用意しました。
表示は以下のようになります。
子コンポーネントのslot
タグ内が空の場合は親コンポーネントのSlotContent
タグ内のコンテンツが挿入され、逆にSlotContent
タグ内にコンテンツがない場合は、子コンポーネントのslotタグ内で指定したテキストの内容が反映されます。
名前付きスロットの指定
親コンポーネントから子コンポーネントに複数のコンテンツをそれぞれ決められた箇所に挿入したいときは名前付きスロット機能を利用します。
以下がその例です。
<script setup lang="ts">
import SlotContent from "./components/SlotContent.vue";
</script>
<template>
<SlotContent>
<template v-slot:header>
<!-- header スロットのためのコンテンツ -->
<h2>ヘッダーのタイトルが入ります。</h2>
<p>ヘッダーのテキストが入ります。</p>
</template>
<template v-slot:default>
<!-- main スロットのためのコンテンツ -->
<h2>メインのタイトルが入ります。</h2>
<p>メインのテキストが入ります。</p>
</template>
<template v-slot:footer>
<!-- footer スロットのためのコンテンツ -->
<h2>フッターのタイトルが入ります。</h2>
<p>フッターのテキストが入ります。</p>
</template>
</SlotContent>
</template>
<script setup lang="ts"></script>
<template>
<div class="container">
<header>
<!-- ここに header コンテンツが必要 -->
<slot name="header"></slot>
</header>
<main>
<!-- ここに main コンテンツが必要 -->
<slot></slot>
</main>
<footer>
<!-- ここに footer コンテンツが必要 -->
<slot name="footer"></slot>
</footer>
</div>
</template>
<style scoped>
header,main,footer {
padding: 5px;
text-align: center;
box-sizing: border-box;
}
header {
background-color: coral;
}
main {
background-color: deepskyblue;
margin: 10px 0;
}
footer {
background-color: goldenrod;
}
</style>
このようにheader
とmain
、footer
を用意して、それぞれに指定した内容のスロットコンポーネントを挿入します。
結果は以下のようになります。
このように各コンテンツを表示させたいエリアに表示させることができました。
それでは解説していきたいと思います。
まずヘッダーの内容をheader
タグの中に、メインのコンテンツをmain
タグの中に、フッターの内容をfooter
タグの中に入れるために、template
内にv-slot:
結び付けたいキーを指定します。
次に子コンポーネントで結び付けたいキーと同様の名前をslot
タグ内にname
属性で指定してあげます。
このようにすることで親コンポーネントでv-slot
で指定したキーを、子コンポーネント側でname
属性を指定することで挿入先を指定することができます。
header
とfooter
は分かるのですがmain
タグ内のv-slot
にはdefault
が指定されていますが、子コンポーネント側にはname
属性がありませんよ・・・name
属性を持たないように見えるslot
タグですが、実は指定なしだと暗黙的にdefault
というname
属性を持っているという特徴があります。
v-slot
側でdefault
を指定することで、指定のないslot
タグに挿入されることになります。
v-slotの省略形
最後にv-slot
の省略形についてご紹介します。
v-bind
が:bind
、v-on:click
が@click
のようにv-slot
も省略形が用意されています。
先程のv-slot:header
を省略する場合は#headerとなります。
<template>
<SlotContent>
<template #header>
<!-- header スロットのためのコンテンツ -->
<h2>ヘッダーのタイトルが入ります。</h2>
<p>ヘッダーのテキストが入ります。</p>
</template>
<template #default>
<!-- main スロットのためのコンテンツ -->
<h2>メインのタイトルが入ります。</h2>
<p>メインのテキストが入ります。</p>
</template>
<template #footer>
<!-- footer スロットのためのコンテンツ -->
<h2>フッターのタイトルが入ります。</h2>
<p>フッターのテキストが入ります。</p>
</template>
</SlotContent>
</template>
v-slot
を省略する場合は「#」を使用するんだね!