0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Vue.js】名前付きslotを用いている時のデフォルトslotが適用される仕組み

Last updated at Posted at 2021-05-23

はじめに

仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

名前付きslotを用いている時のデフォルトslotが適用される仕組み

slotの基本

<slot></slot>を用いる事で親→子でhtmlの受け渡しを実現できる。
image.png

parent.vue
<template>
  <div>
    <LikeHeader>
      <h1>トータルのいいね数</h1>
      <h2>{{ number }}</h2>
    </LikeHeader>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
  },
};
</script>
child.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

デフォルトslot(フォールバックコンテンツ)

親コンポーネント側から何も<slot></slot>に渡ってこない場合に、デフォルトで何かを表示させる必要がある時にはデフォトslotを用いる。
デフォルトslotは<slot></slot>の中にhtmlを書くとそれがデフォルトslotになる。
image.png

parent.vue
<template>
  <div>
    <LikeHeader>
      <!-- <h1>トータルのいいね数</h1> -->
      <!-- <h2>{{ number }}</h2> -->
    </LikeHeader>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
  },
};
</script>
child.vue
<template>
  <div>
    <slot>
      <h2>デフォルトのタイトル</h2>
    </slot>
  </div>
</template>

名前付きslot

親コンポーネント側で複数のhtml要素を定義し、子コンポーネント側では指定のslotにそれを描画させたいという場合には名前付きslotを用いる。
これにより親コンポーネントで定義したhtml要素を意図した子コンポーネントのslotに渡すという複雑な実装が実現できる。
以下の実装では、

  1.  <h1>トータルのいいね数</h1>
  2.  <h2>{{ number }}</h2>

という2つのhtml要素をそれぞれtitlenumberという名前付きslotに渡している。
image.png

parent.vue
<template>
  <div>
    <LikeHeader headerText="hello">
      <template v-slot:title>
        <h1>トータルのいいね数</h1>
      </template>

      <template v-slot:number>
        <h2>{{ number }}</h2>
      </template>
    </LikeHeader>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
  },
};
</script>
child.vue
<template>
  <div>
    <slot name="title"></slot>
    <hr />
    <slot name="number"></slot>
  </div>
</template>

名前付きslotを用いる場合、親コンポーネントでhtml要素を定義する際には、<template v-slot:hogehoge></template>のようにtemplateタグ内にhtml要素を記述し、v-slotディレクティブで名前1を定義する必要がある。
受け取る子コンポーネント側では、name属性を記述しそこにv-slotディレクティブで定義した名前を代入する事でslotが機能する。

※slotを用いる際には必ず<template></template>を用いないとエラーになるので注意。

名前付きslotを用いている時のデフォルトslotが適用される仕組み

名前付きslotを用いている場合のデフォルslotは以下のように実装できる。
image.png

parent.vue
<template>
  <div>
    <LikeHeader headerText="hello">
      <h2>みなさん</h2>

      <template v-slot:title>
        <h1>トータルのいいね数</h1>
      </template>

      <h4>いいねをたくさんもらいましょう</h4>
      <p>よろしくお願いします</p>

      <template v-slot:number>
        <h2>{{ number }}</h2>
      </template>
    </LikeHeader>
  </div>
</template>

<script>
import LikeHeader from "./components/LikeHeader.vue";
export default {
  data() {
    return {
      number: 10,
    };
  },
  components: {
    LikeHeader,
  },
};
</script>
child.vue
<template>
  <div>
    <slot name="title"></slot>
    <hr />
    <slot></slot>
    <hr />
    <slot name="number"></slot>
  </div>
</template>

親コンポーネントで<template></template>で囲われていない部分がデフォルslotに渡るhtml要素であり、子コンポーネントで<slot></slot>と記載している部分がデフォルトslot(フォールバックコンテンツ)になる。

ここで、このデフォルトslotがどのように実現されているか?を詳しく見ていく。
実は、親コンポーネントで<template></template>で囲われていない部分は、Vue.js側で以下のように解釈されて<template></template>に囲われているものとして扱われる。この時、v-slotディレクティブも自動的に付与されるがv-slot:defaultがそれ。

<template v-slot:default>
  <h2>みなさん</h2>
  <h4>いいねをたくさんもらいましょう</h4>
  <p>よろしくお願いします</p>
</template>

そして実は子コンポーネントの<slot></slot>もVue.js側で以下のように解釈され、defaultという名前の名前付きslotに置き換えられている。

<slot name="default"></slot>

そのため、以下のようなソースコードでも上記の図と同じ結果になる。

  1.  子コンポーネントの<slot></slot>をわざと<slot name="default"></slot>にする(親コンポーネントは変えないで)
  2.  親コンポーネントのデフォルトのhtml要素を<template v-slot:default></template>内にわざと記述する(子コンポーネントは変えないで)
  3.  上記1・2の親・子それぞれの変更を行う

※このような仕組みなので名前付きslotの名前をdefaultにしてしまうと意図しない動きになるので注意が必要。

#
子コンポーネントでname="title"name="default"にする image.png
親コンポーネントで<template v-slot:title><template v-slot:default>にする image.png

Vue.jsの勉強メモ一覧記事へのリンク

Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

  1. これはv-slotディレクティブの第1引数に値を渡す事で実現されている

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?