Written by TSUYOSHI

Vue・Nuxtでslotの中身の有無で処理を分ける方法 【$scopedSlotsを使います】

JavaScript PROGRAMMING Vue

VueやNuxtで、slotの利用時に、v-slotでslotの処理を複数に分けていて、slotが渡されていれば表示・slotが渡されていなければ非表示にするというような処理を書きたい時に使える便利な方法について解説します。

この記事を書いている僕は、フロントエンドのプログラマー(フリーランス)として、これまで4年ほどのWeb制作経験があり、Vue,React,Nuxtなどフロントエンドの開発を得意としています。

この記事を読むことによって、Vueのslotで中身の有無により処理を切り分けることができるようになります。

Vue・Nuxtでslotの中身の有無で処理を分ける方法 【$scopedSlotsを使う】

結論としては、公式にもある$scopedSlotsを使うことによって、v-ifによる処理の切り分けができるようになります。

ちなみにVueのslotの基本的な使い方を知りたい方は「【Vue】slotの使い方 【名前付きスロット・スロットプロパティ・省略記法】」の記事をご覧ください。

具体的な例を挙げていきます。

▼親コンポーネント

<template>
  <div class="block">
    <ExampleChild>
      <template v-slot:title>
        <span>Example: slotの有無で表示を切り分ける方法</span>
      </template>
      <template v-slot:description>
        <p>こんにちは、山田さん</p>
      </template>
    </ExampleChild>
  </div>
</template>

▼子コンポーネント (修正前:通常)

<template>
  <div class="block">
    <h1>
      <slot name="title"></slot>
    </h1>
    <div class="container">
      <slot name="description"></slot>
    </div>
  </div>
</template>

上記のようなコードがあった場合、name="title"name="description"のコンテンツの両方があれば問題ないのですが、例えばname="title"slotで渡されない場合は、空のh1タグが残ってしまいます。こういう時に「this.$scopedSlotstitle」「this.$scopedSlots.description」など「$scopedSlots」によって判定することが可能になります。

▼子コンポーネントの修正の例 (修正後)

<template>
  <div class="block">
    <h1 v-if="this.$scopedSlots.title">
      <slot name="title"></slot>
    </h1>
    <div
       v-if="this.$scopedSlots.description"
      class="container"
    >
      <slot name="description"></slot>
    </div>
  </div>
</template>

このように「this.$scopedSlots」を利用することで、slotの有無によりv-ifのブロックごと非表示にすることが可能です。

また複数ではなく単一のslotタグを使っている際に判定したい際は「this.$scopedSlots.default」を使った判定をすれば同じことができるようになります。

ちなみにVueバージョン2.6.0以降では、$slots$scopedSlotsにも関数として公開されるようになり、常に $scopedSlots 経由でスロットにアクセスすることが推奨されるようになりました。$slotsではなく、$scopedSlotsを使うようにしましょう。

ご参考になれば幸いです。