🗒️

【Nuxt.js v2】v-slotの指定方法

2021/03/20に公開

デフォルトスロットの指定

<template v-slot:default>・・・</template>

<!-- デフォルトスロットの場合はスロット名を省略できる。 -->
<template v-slot>・・・</template>

<!-- v-slot自体も省略できる。 -->
<template>・・・</template>

名前付きスロット

<!-- 名前付きスロット -->
<template v-slot:header>・・・</template>

<!-- v-slot:は#で省略できる。 -->
<template #header>・・・</template>

<!-- v-slotを省略したデフォルトスロットと、共存できる。 -->
<template>・・・</template>
<template #header>・・・</template>

スロットプロパティ

<div>
  <slot :name="name">
    {{ name }}
  </slot>
</div>

上記のように定義されたスロットプロパティを、以下のように利用側(親コンポーネント)で参照できる。
任意の変数名(以下のprops)で受け取り、その変数のプロパティとして格納されている。

<template #default="props">
  {{ props.name }}
</template>

以下のように分割代入を使用すれば、スロットプロパティをそのまま受け取れるため、記述が簡素になる。

<template #default="{ name }">
  {{ name }}
</template>

スロットプロパティに別名をつけることが可能
同じスコープ内で他のプロパティや変数と名前が被ってしまう場合に使える。
(以下ではnameというプロパティをuserNameという名前につけかえて取得)

<template #default="{ name: userName }">
  {{ userName }}
</template>

動的なスロット名

変数の値で動的にスロット名を指定できる。
(v-slot:は#で省略)

<!-- 変数slotNameに指定したいスロット名を格納している。 -->
<template #[slotName]>・・・</template>

以下のパターンは、itemオブジェクトのnameに格納された文字列をスロット名として指定している。

<template #[item.name]>・・・</template>

特殊なパターン

slot名に.(ピリオド)が使用されている場合は以下のようにする。
自作のコンポーネントではまず無いが、Vuetifyのv-data-tableを使用する際にこのような記述を必要とする場合がある。

<template #item.name>・・・</template>

ESLintを導入していて'v-slot' directive doesn't support any modifierというエラーが出る場合は、以下のように書き換える。

<template #[`item.name`]>・・・</template>

※ なぜこうなるか

  1. ピリオドが、v-onで使用するイベント修飾子と認識されてしまい、「'v-slot'は修飾子をサポートしてないよ!」と指摘される。(イベント修飾子の例→v-on:click.stop
  2. ピリオドを含め文字列として認識させるために、[]での動的スロット名に文字列を渡すことで解決する。
  3. 動的なスロット名指定に、普通のクオーテーションで囲んだ文字列を渡すと、以下のエラーが発生する。
    Invalid dynamic argument expression: attribute names cannot contain spaces, quotes, <, >, / or =.(動的引数式に引用符などは含められない。)
  4. ``(バッククオーテーション)を使用したテンプレート構文で文字列を渡せば上記エラーは解決する。

このようにして、#[`item.name`]となる。

Discussion