【学習記録⑦】slotを用いてコンポーネント間でデータの受け渡しを行う。

#はじめに
Vue.jsを最近勉強し始めたので学んだ文法などを備忘録としてメモしていこうと思います。
[前々回の学習記録記事](https://qiita.com/Ooooooomin_365/items/7449f72409bf6d00f475)、および[前回の学習記録記事](https://qiita.com/Ooooooomin_365/items/63eef765efc78672714e)では`props`や`$emit`を用いて親子のコンポーネント間でデータの受け渡しをしていましたが、今回の記事では`slot`や`slotProps`を用いてデータの受け渡しを行っていこうと思います。

##slotを用いてHtmlを子コンポーネントへ渡す
`props`では特定の値などを子コンポーネントへ渡していましたが`slot`を用いるとHtmlを子コンポーネントに渡すことができます。

```vue:親.vue
<template>
  <div>
    <child>
      <div>おはようボタン</div>
    </child>
  </div>
</template>
```

```vue:子.vue
<template>
  <div>
    <slot></slot>   <-- 親.vueの「<div>おはようボタン</div>」が入ってくる
  </div>
</template>
```

複数の`slot`を渡す際は`名前付きslot`を用います。

```vue:親.vue
<template>
  <div>
    <child>
      <template v-slot:morning>
        <div>おはようボタン</div>
      <template>
      <template v-slot:afternoon>
        <div>こんにちはボタン</div>
      <template>
    </child>
  </div>
</template>
```

```vue:子.vue
<template>
  <div>
    <slot name="morning"></slot>  <-- 親.vueの「<div>おはようボタン</div>」が入ってくる
    <slot name="afternoon"></slot>  <-- 親.vueの「<div>こんにちはボタン</div>」が入ってくる
  </div>
</template>
```

子コンポーネントから親コンポーネントに値を渡す際は`$emit`でもできますが`slotProps`を用いて渡すことも可能です。
以下では`{{ slotProps }}`部分に`{ "text": "あああ" }`という形で値が渡ってきます。

```vue:親.vue
<template v-slot:test="slotProps">
  <div>{{ slotProps }}</div>
</template>
```

```vue:子.vue
<template>
  <div>
    <slot name="test" :text="text"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      text:"あああ"
    };
  }
};
</script>
```

## 以上を用いてサンプルを作ってみる
基本的には`slot`の勉強を主な目的として、簡単なサンプルを作ってみました。

* 「おはようボタン」をクリックすると`おはよう～！`とアラートが出る
* 「メッセージ変更」ボタンをクリックし、再度「おはようボタン」をクリックすると`おはよう～！子から変更～`というアラートに変更される
* 「子からのデータ出現」ボタンをクリックすると`子からのおはようタイトルでした！`という文字が表示される

###サンプルコード
```vue:App.vue
<template>
  <div>
    <morning @change-morning-message="changeMorningMessage">
      <template v-slot:default="slotProps">
        <button @click="alertMorningMessage">おはようボタン</button>
        <div v-if="slotProps !== ''">{{ slotProps.title }}</div>
      </template>
    </morning>
  </div>
</template>

<script>
import Morning from "./components/Morning.vue";

export default {
  data() {
    return {
      morningMessage: "おはよう～！",
    };
  },
  components: {
    Morning,
  },
  methods: {
    alertMorningMessage() {
      alert(this.morningMessage);
    },
    changeMorningMessage(value) {
      this.morningMessage = value;
    },
  },
};
</script>
```

```vue:Morning.vue
<template>
  <div>
    <slot :title="title"></slot>
    <button @click="changeMessage">メッセージ変更</button>
    <button @click="setTitle">子からのデータ出現</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: ""
    };
  },
  methods: {
    changeMessage() {
      this.$emit("change-morning-message", "おはよう～！子から変更～");
    },
    setTitle() {
      this.title = "子からのおはようタイトルでした！";
    },
  },
};
</script>
```

###結果
「おはようボタン」をクリックすると以下のようにアラートが出ます。
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/79594736-7fed-a00f-1402-f7d656c1288b.png)

「メッセージ変更」ボタンをクリックし、再度「おはようボタン」をクリックすると`おはよう～！子から変更～`というアラートに変更されていることが分かります。
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/9c9eae67-da07-1d75-3e7d-8bbbdf2ae38c.png)

「子からのデータ出現」ボタンをクリックすると`子からのおはようタイトルでした！`という文字が表示されます。
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/b882c82a-62c8-b5c0-8202-e738f926fb40.png)

#おわりに
今のところVue.jsはとても分かりやすくて楽しいです！
引き続き学習を続けていきたいと思います！