【Nuxt.js】slot応用編：コンポーネントに自由にデータを渡そう

#前置き
Vue.jsとNuxt.jsで便利なslotを使ってみましょう！
今回は実践・応用編です！
（全体のまとめ、propsとの違いは文字数オーバーのため次回に…）
ご意見やご感想、いつでもお待ちしております！

いやいや、基礎が知りたいんじゃ！という方は
基礎編へどうぞ
超簡単な解説から実践編までを解説しています。




#slotを使おう！実践・応用編
では、ここからは実際にコードを書いてみましょう。
作る物はこちら！

【表示結果】

![picture_pc_abf2c39d55171acc2d9162c6cda967a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/9e98bffe-d0a1-8429-f7ad-405c5900294b.png)


アイコンはICOON MONOさんでお借りしております。
callとmailで検索すればヒットします。
https://icooon-mono.com/



構造
お問い合わせページで
電話かメールかを選択していただき、
それぞれの詳細ページに飛ぶようなボタンを作ります。
・画像(imgもしくはsvgが入る)とpが入ったシンプルなボタン。
・ボタンは幅によって可変に。
・余白や幅の値など、スタイリングは大体で良いです。
・リンク先は記載しなくて良いです。
　やりたい方は次の  #slotを使おう！実践・応用編+α へどうぞ
・slotを使って見た目が出来ていればOK！

Let's try!

…


あれ、分からんって方は基礎編へどうぞ！

頭ごちゃごちゃしてきたって方は
スタイリングは一旦無視しましょうw
slotができてから、後からスタイリングしてみてください。


…

できましたか？
答えはこちら！！
スタイリングはscssで記載してますが、通常のcssでももちろんOKです！

【コード】

```ButtonDefault.vue
ButtonDefault.vue // 子コンポーネント
<template>
 <button class="button-default">
   <slot />
   <p>
     <slot name="label" />
   </p>
 </button>
</template>

<script>
 export default { }
</script>

<style lang="scss" scoped>
 .button-default {
   cursor: pointer;
   display: block;
   text-align: center;
   height: 150px;
   border-radius: 8px;
   border: 1px solid #dddddd;

   &:hover {
     transform: scale(1.04);
     transition-duration: 40ms;
   }

   > p {
     margin-top: 20px;
     font-family: 'Noto Sans CJK JP';
     font-size: 20px;
     letter-spacing: 0.1em;
   }
 }
</style>
```



```index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <div class="buttons">
     <ButtonDefault class="button">
       <img class="img" src="/callcenter.png" alt="">
       <template v-slot:label>
         お電話でのお問い合わせ
       </template>
     </ButtonDefault>
     <ButtonDefault class="button">
       <img src="/mail.png" alt="">
       <template v-slot:label>
         メールでのお問い合わせ
       </template>
     </ButtonDefault>
   </div>
 </div>
</template>

<script>
import ButtonDefault from '~/components/Buttons/ButtonDefault.vue';
export default { }
</script>

<style lang="scss" scoped>
 .page {
   padding: 20px;
   > .buttons {
     display: flex;
     justify-content: space-between;
     > .button {
       width: calc(50% - 11px);
       > img {
        with: 36px;
       }
     }
   }
 }
</style>
```

できましたか？🤩

Point！
・画像slotをsvgなどで囲まない
　imgかsvgどちらでも使えるようにしたいので、
　画像は親で指定します。
　＝スタイリングは親で行う
　＝どうしても子で書く場合はdivで囲む

・pタグはslotを囲む
　どこで使われてもpタグ！
　急にh1になったりしないため固定

・slot nameを使う場合、それぞれにつけなくても良い
　2つslotがあれば、片方のみnameをつければ区別ができるため
　余計な物は除去！
　(前回の記事では、
　分かりやすく説明するため2つともnameをつけていますが…！)

・親ではtemplate v-slot: で指定

・ボタン同士の余白など、配置は親で指定


おめでとうございます！
これでslotには慣れましたね🎉
+α ぜひチャレンジしてください！



#slotを使おう！実践・応用編 +α
![picture_pc_abf2c39d55171acc2d9162c6cda967a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/64a58744-4a4d-9760-f6cc-6bf940d2758c.png)


・slot利用
・リンク先追加ver.
・nuxt-linkや$attrsを使用
ディレクトリ の構造はファイル名は下記とします。

```
components/
--| Buttons/
-----| ButtonDefault.vue

pages/
--| contact/
-----| call.vue
-----| mail.vue
--| index.vue
```
Let's try!

…
コンポーネント自体にnuxt-linkつけるって…
こうかな？

```index.vue
<nuxt-link to="/contact/call">
 <ButtonDefault>
  <img class="img" src="/callcenter.png" alt="">
  <template v-slot:label>
   お電話でのお問い合わせ
  </template>
 </ButtonDefault>
</nuxt-link>
```

というかattrsってなんじゃ？
と思っていました😂
これはダメですw


さぁ答えを見てみましょう！

スタイリングなどは同じのため、
template内のみ記載します！

【コード】

```ButtonDefault.vue
ButtonDefault.vue // 子コンポーネント
<template>
 <nuxt-link
  v-bind="$attrs"
  class="button-default"
 >
   <slot />
   <p>
     <slot name="label" />
   </p>
 </nuxt-link>
</template>
```

```index.vue
index.vue // 親ページ
<template>
 <div class="page">
   <div class="buttons">
     <ButtonDefault to="/contact/call" class="button">
       <img class="img" src="/callcenter.png" alt="">
       <template v-slot:label>
         お電話でのお問い合わせ
       </template>
     </ButtonDefault>
     <ButtonDefault to="/contact/mail" class="button">
       <img src="/mail.png" alt="">
       <template v-slot:label>
         メールでのお問い合わせ
       </template>
     </ButtonDefault>
   </div>
 </div>
</template>
```

Point！
・子でbuttonタグをnuxt-linkにする
　リンク先を$attrsにし、親で遷移先を自由に指定する

・親で読み込んだコンポーネントに遷移先を指定
　to="/contact/call" の部分



読み込んだコンポーネントに直接nuxt-linkを指定する方法が
検索してもなかなか出てきませんでした。。。
でもこれで大丈夫！
あなたも今日からslotマスターです🎉✨