【Nuxt.js】slot上級編：意外と知らない！slotの便利な使い方

# 前置き
slot応用編に入れる予定だった
総合まとめが入り切らず
上級編にしました！
slot基礎編、応用編どちらも
クリアした方向けです。


# こんな使い方もできる！
今まで紹介してきたslotは
子でslot、親にテキストでしたが、
今回はちょっと違うパターンです！

**こういったモーダルウィンドウ 
いくつも作りたい場合。
テキストの外側の装飾、
いちいち書くのは面倒ですね…！
そして中身も１つ１つ
別のコンポーネントを作りたい、**
そんな時の使い方です。

![picture_pc_2cd68c7070c8380f16a27a037343a750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/a35656ac-50ea-6552-742e-b52624b7c8cc.png)

アイコンはiconmonstrさんでお借りしました。
closeで検索、
svgコードを貼り付けて使用しております。
https://iconmonstr.com/

**まずは外側のコンポーネントを作成**
(背景の白い部分と閉じるボタン)
中身をslotで自由にデータを表示させます。
slotの使い方が分かれば良いので、
スタイリングは省きます。

```ModalWrap.vue
ModalWrap.vue // モーダルの外側
<template>
 <div class="modal-wrap">
   <button class="button" @click="$emit('close')">
     <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 20.188l-8.315-8.209 8.2-8.282-3.697-3.697-8.212 8.318-8.31-8.203-3.666 3.666 8.321 8.24-8.206 8.313 3.666 3.666 8.237-8.318 8.285 8.203z"/></svg>
   </button>
   <slot />
 </div>
</template>

<script>
</script>

<style lang="scss" scoped>
</style>
```

**中身のコンポーネントを作成**

```ModalText.vue
ModalText.vue // モーダルの中身
<template>
 <div class="modal-text">
  <p>Hello Nuxt.js!</p>
 </div>
</template>

<script>
</script>

<style lang="scss" scoped>
</style>
```

**親ページでModalTextをModalWrapで囲む**

```index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <div v-if="active" class="modal">
     // グレーの背景
     <div class="background" />
     // ModalWrapのslot部分がModalTextに置き換わる
     <ModalWrap @close="active = false">
       <ModalText />
     </ModalWrap>
   </div>
 </div>
</template>

<script lang="ts">
import ModalWrap from '~/components/ModalWrap.vue'
import ModalText from '~/components/ModalText.vue'

export default {
 components: {
  ModalWrap,
  ModalText,
 },
 data () {
   return {
     active: false,
   }
 },
})
</script>

<style lang="scss" scoped>
</style>
```

これだけです！
とっても便利ですよね😄

# Vue.jsバージョン 2.6.0での使い方
追加された新機能、 **v-slot:を#で省略して書いてます。**
使い方自体は一緒です！
省略できるよ、いえーいってだけ。
v-slot: titleなら #title になります。

```ItemTitle.vue
ItemTitle.vue // 子コンポーネント
<template>
 <h2 class="item_title">
  <slot name="title">
   Title // ここはslotで置き換えられるため消える
  </slot>
  <span>
   <slot name="catchCopy">Catch Copy</slot>
  </span>
 </h2>
</template>
```

```index.vue
index.vue // 親ページ
<ItemTitle>
 <template #title>  // v-slot:を#で省略(v-slot:title)
  {{ hero.title }} 
 </template>
 <template #catchCopy>  // v-slot:を#で省略(v-slot:catchCopy)
  {{ hero.catchCopy }} 
 </template>
</ItemTitle>

<script>
import ItemTitle from '../components/ItemTitle.vue';
export default {
 data () {
   return {
     hero: {
       title: "PageTitle",
       catchCopy: [
           "catchCopy1",
           "catchCopy2"
       ]
     },
   }
 },
 components: {
   ItemTitle: ItemTitle,
 }
}
</script>
```


```vue
表示結果
<h2 class="item_title">
 PageTitle 　// json内のhero.titleが呼び出される
  <span>catchCopy catchCopy</span>　// json内のhero.catchCopyが呼び出される
</h2>
```


省略で書いた方が
分かりやすいかもしれませんね🎈

#まとめ
色々やってきましたが、
超シンプルにまとめます。
slotで改行しなくて良いのですが、
slot部分を強調するため改行しています。

**・slot 1つ**
子slot、親にテキスト

```Component.vue
Component.vue // 子コンポーネント
<h1>
 <slot>ここに書いたものは無視される</slot>
</h1>
```

```index.vue
index.vue // 親ページ
<Component>
 slotを学ぼう！
</Component>
```

**・slot 2つ以上**
　デフォルト1つと、
　他にslot nameつける

　親でtemplateでslotを置き換える
　template v-slot:name
　もしくは
　template #name

```Component.vue
Component.vue // 子コンポーネント
<slot />
<h1>
 <slot name="title" /> 
</h1>
<h2>
 <slot name="subTitle" /> 
</h2>
```

```index.vue
index.vue // 親ページ
<Component>
 <img src="~">
 <template #title>
  slotを学ぼう！
 </template>
 <template #subTitle>
  slotを使おう！
 </template>
</Component>
```

　ちなみにどちらもslot nameつけたのに
　v-slotしないと子の内容が直接反映されます。

```Component.vue
Component.vue // 子コンポーネント
<div>
 <h1>
  <slot name="title">Hello Nuxt.js!</slot>
 </h1>
 <h2>
  <slot name="subTitle">slotを学ぼう！</slot>
 </h2>
</div>
<div>
 <p>
  <slot />
 </p>
</div>

<style scoped>
div {
 border: 1px solid pink
}
</style>
```

```index.vue
index.vue // 親ページ
<Component>
 <template #title>
   ハロー！
 </template>
 やっほー！
</Component>
```

```vue
表示結果
<div class="ItemTitle">
 ハロー！
 slotを学ぼう！
</div>
```

slotは沢山記事にしましたが、
まとめると超簡単ですよね🤗


**このアカウントでは
Nuxt.js、Vue.jsを誰でも分かるよう、
超簡単に解説しています🎈😀
これからも発信していくので、
ぜひフォローしてください♪**
https://twitter.com/aLizlab