VueJS 速習チュートリアル

Vue.js スロット(Slots)

スロット(Slots)は Vue における強力な機能であり、コンポーネントの柔軟性と再利用性を高めるために利用されます。
Vue のスロットを使用すると、親コンポーネントから子コンポーネントの <template> 内にコンテンツを送り込むことができます。

1. スロットの基本

これまでの学習では、<template> 内でコンポーネントを呼び出す際、次のような自己完結型のタグとして使用してきました。

App.vue:

<template>
  <slot-comp />
</template>

しかし、スロットを利用すれば、開始タグと終了タグを使用し、その間にテキストなどのコンテンツを挿入することができます。

App.vue:

<template>
  <slot-comp>Hello World!(ハロー・ワールド)</slot-comp>
</template>

この「Hello World!」を子コンポーネント側で受け取り、ページに表示させるには、コンポーネント内で <slot> タグを使用する必要があります。<slot> タグはコンテンツのプレースホルダとして機能し、アプリケーションがビルドされた後、<slot> は送られてきたコンテンツに置き換わります。

1.1 実装例

SlotComp.vue:

<template>
  <div>  
    <p>SlotComp.vue(子コンポーネント)</p>
    <slot></slot>
  </div>
</template>

2. スロットをカードとして活用する

スロットは、動的な HTML コンテンツの大きな塊をラップして、カード(Card)のような外観を作るためにも使用できます。

以前はコンポーネント内のコンテンツを作成するために props でデータを送っていましたが、スロットを使えば HTML コンテンツをそのまま直接 <slot> タグに送り込むことが可能です。

2.1 実装例

App.vue:

<template>
  <h3>Vue におけるスロット</h3>  
  <p>foods 配列からカード形式の div ボックスを作成します。</p>
  <div id="wrapper">
    <slot-comp v-for="x in foods" :key="x.name">
      <img v-bind:src="x.url">
      <h4>{{x.name}}</h4>
      <p>{{x.desc}}</p>
    </slot-comp>
  </div>
</template>

コンテンツが <slot> のあるコンポーネントに入ると、その <slot>div で囲み、その div に対してローカルにスタイルを適用します。これにより、アプリケーション内の他の div に影響を与えることなく、コンテンツの周囲にカードのような外観を作成できます。

SlotComp.vue:

<template>
  <div> <slot></slot>
  </div>
</template>

<script></script>

<style scoped>
  div {
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
    border-radius: 10px;
    margin: 10px;
    padding: 10px;
  }
</style>

コンテンツの周囲にカード型のフレームを生成するコンポーネントは、異なる要素に対しても同じフレームを使い回すことで再利用できます。
次の例では、食べ物のアイテムに使ったものと同じコンポーネントを使用して、フッターを作成しています。

App.vue:

<template>
  <h3>再利用可能なスロットカード</h3>
  <p>foods 配列からカード形式の div ボックスを作成します。</p>
  <p>また、同じコンポーネントを再利用してカード形式のフッターも作成します。</p>
  <div id="wrapper">
    <slot-comp v-for="x in foods" :key="x.name">
      <img v-bind:src="x.url">
      <h4>{{x.name}}</h4>
    </slot-comp>
  </div>
  <footer>
    <slot-comp>
      <h4>フッター内容</h4>
    </slot-comp>
  </footer>
</template>

3. フォールバックコンテンツ(Fallback Content)

コンポーネントがコンテンツなしで呼び出された場合に備えて、<slot> 内にフォールバックコンテンツ(代替コンテンツ)を設定しておくことができます。

3.1 実装例

このアプリケーションの最初のコンポーネントにはコンテンツが渡されていないため、フォールバックコンテンツがレンダリングされます。

App.vue:

<template>
  <h3>スロットのフォールバックコンテンツ</h3>
  <p>コンテンツが提供されないコンポーネントでは、slot タグ内のフォールバックコンテンツが表示されます。</p>
  <slot-comp>
    </slot-comp>
  <slot-comp>
    <h4>このコンテンツは App.vue から提供されています</h4>
  </slot-comp>
</template>

SlotComp.vue:

<template>
  <div>
    <slot>
      <h4>これはフォールバックコンテンツ(デフォルト)です</h4>
    </slot>
  </div>
</template>