Vue.jsの勉強を進めていてslotの考え方がわからなかったのですが、いわゆる「完全に理解した」くらいまでは理解が進んだかなと。
slot、理解して使いこなせれば柔軟にコンポーネント設計ができるようになると思います。
環境
検証に使用した環境は以下の通りです。
Vue:2.6.11
省略記法やv-slotディレクティブなど、2.6.0から追加になった記法が幾つかあるため、インストールしているVueのバージョンを確認してください。
slotとは
HTMLを小分けしたのがいわゆるcomponent(コンポーネント)。コンポーネントの中で、さらに小さい単位のコンポーネント(っぽい領域)を確保するのがslot(スロット)
と理解しました。
サンプルコード
サンプルとして、以下2つのコンポーネントを用意しました。
- App.vue(親コンポーネント)
- SlotComponent.vue(子コンポーネント)
各コードは以下の通りです。
App.vue
<template>
<div id="app">
親コンポーネントの中身は、この領域です。
<SlotComponent>
<template v-slot:default="piyo">
<div>名前無しスロットは、この領域です。</div>
<div>プロパティも受け渡せます。{{ piyo.prop }}</div>
</template>
<template v-slot:one>
<div>スロット「one」は、この領域です。</div>
<div>(v-slotでスロット名を指定します)</div>
</template>
<template #two="piyo">
<div>スロット「two」は、この領域です。プロパティは{{ piyo.prop.hoge }}です</div>
<div>(省略記法は「#」です)</div>
</template>
<template v-slot:three></template>
<template v-slot:four>
スロット「four」は、存在しないです。
</template>
</SlotComponent>
</div>
</template>
<script>
import SlotComponent from './components/SlotComponent.vue'
export default {
name: 'App',
components: {
SlotComponent
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
SlotComponent
<template>
<div class="component">
ここはコンポーネントですが、slotではない領域です。
<div class="slot-default">
<slot v-bind:prop="defaultProp">
<div>名前無しスロットのフォールバックコンテンツです。</div>
</slot>
</div>
<div class="slot-one">
<slot name="one">
<div>スロット「one」のフォールバックコンテンツです。</div>
</slot>
</div>
<div class="slot-two">
<slot name="two" v-bind:prop="objectProp">
<div>スロット「two」のフォールバックコンテンツです。</div>
</slot>
</div>
<div class="slot-three">
<slot name="three">
<div>スロット「three」のフォールバックコンテンツです。</div>
</slot>
</div>
</div>
</template>
<script>
export default {
name: 'SlotComponent',
data: function() {
return {
defaultProp: "defaultのプロパティ",
objectProp: {
hoge: "fuga"
},
}
}
}
</script>
<style>
.component {
border: 1px solid #ddd;
}
.slot-default {
background-color: #ccffcc
}
.slot-one {
background-color: #ffffcc
}
.slot-two {
background-color: #ffe5cc
}
.slot-three {
background-color: #ccffe5
}
</style>
上記コードの実行結果は以下のようになります。

以降、slot関連で使用している機能を見ていきます。
名前付きスロットと名前無しスロット
名前付きスロット
<slot name="one">
<div>スロット「one」のフォールバックコンテンツです。</div>
</slot>
slotの定義時にname属性を付与する事で、slotに任意の名前を指定できる。要素の中身はフォールバックコンテンツ(=デフォルトの値)となる。
名前無しスロット
<slot v-bind:prop="defaultProp">
<div>名前無しスロットのフォールバックコンテンツです。</div>
</slot>
slotの定義時にnameを指定しなければ、名前無しスロットとなり、暗黙的にdefaultという名前が指定される。
※上記はv-bindでプロパティを受け渡ししているが、nameを指定していない為、名前無しスロットとなる。
デフォルト値の設定
<slot name="three">
<div>スロット「three」のフォールバックコンテンツです。</div>
</slot>
slot要素の中身はフォールバックコンテンツ、つまりデフォルトの値となり、呼び出し側(親コンポーネント)で中身を指定しない場合に、フォールバックコンテンツが設定されます。
![]()
プロパティの受け渡し
SlotComponent.vue
<slot v-bind:prop="defaultProp">
<div>名前無しスロットのフォールバックコンテンツです。</div>
</slot>
App.vue
<template v-slot:default="piyo">
<div>名前無しスロットは、この領域です。</div>
<div>プロパティも受け渡せます。{{ piyo.prop }}</div>
</template>
コンポーネントでプロパティを使用するのと同じイメージで、v-bindディレクティブでプロパティを受け渡す事ができます。
上記はdefaultPropというプロパティを、piyoという名前で受け取っています。値へのアクセスはバインドした名前になる為、piyo.propでアクセスが可能です。