Vue.jsのslotを完全に理解したので自分の言葉でまとめます

Vue.jsのslotを完全に理解したので自分の言葉でまとめます
                 
最終更新日から90日以上経過しています。

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

JavaScript(TypeScript)カテゴリの最新記事