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でアクセスが可能です。