Vueのコンポーネントを学ぶ

#はじめに
vue.jsをまた基礎から学びなおしているのですが、コンポーネントがなかなか理解した！と自信を持って言えないところです。
[公式ドキュメント](https://jp.vuejs.org/v2/guide/index.html)に沿って覚えたことを自分用解説つきで書いていきます。

#コンポーネントとは
>コンポーネントシステムは Vue.js におけるもうひとつの重要な抽象概念です。「小さく、自己完結的で、（多くの場合）再利用可能なコンポーネント」を組み合わせることで、大規模アプリケーションを構築することが可能になります。アプリケーションのインターフェイスについて考えてみると、ほぼすべてのタイプのインターフェイスはコンポーネントツリーとして抽象化することができます

例えば、webページに共通のヘッダーフッターをすべてのページに出すとき、すべてのファイルにHTML分ちまちま書いたりしたくないですよね。このヘッダーフッターを再利用できるパーツ（再利用可能なコンポーネント）にしちゃおう！という感じです。

#簡単なコンポーネントを作って表示してみる
文字読んでてもよくわからないので一旦作ってみます。
サイトでよく見る、会社名と選択中のタイトル（見出し）を表示するやつをコンポーネント化してみます。
※コンポーネントの理解が主目的なので文言やデザインは超適当です。

componentsの直下に`Header.vue`を作成します

```Header.vue
<template>
  <div class="header">
    <h1>会社名</h1>
    <span>見出し</span>
  </div>
</template>

<script>
export default {
  name: 'Header',
}
</script>

<style scoped>
.header {
    background-color: #2fa16e;
    color: aliceblue;
}
</style>
```

この作ったコンポーネントを使用してみます。今回は`Index.vue`というファイルで使用します

```Index.vue
<template>
  <div id="app">
      <Header/> // 3
  </div>
</template>

<script>
import Header from './components/Header.vue' // 1

export default {
    name: "Index",
    components: {
        Header // 2
    },
}
</script>
```
1.`Header.vue`をimportします。importしたものをここでは`Header`と呼ぶよ。という記述
2.`Header`をコンポーネントとして扱ういますという記述
3.実際に使用
という感じです。

親：Index.vue
子：Header.vue
の関係になります。

実行して`Index.vue`を表示した結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/b35a5313-27a2-d668-55db-0887c280e3bd.png)

作成した`Header.vue`コンポーネントが表示されました。

##使用するコンポーネント名を変えたいとき
先ほどの書き方では`Header.vue`を`Header`という名前としてimportして使用しましたが、`<>`内での名称を変更することができます。

```Index.vue
<template>
  <div id="app">
      <HeaderName/>
  </div>
</template>

<script>
import Header from './components/Header.vue'

export default {
    name: "Index",
    components: {
        "HeaderName": Header //ここを変更
    },
}
</script>
```
`Header`をコンポーネントとして使用するときは`HeaderName`という名前とするよ、という記述です。
それ以外の関数で`Header.vue`使用する場合はそのまま`Header`となります。

#プロパティを受け取れるようにする【props】
先ほどの例では「会社名」「見出し」の文言が固定でしたが、文言をページごとに変えたい場合も多いと思います。
`props`を使用することで親のスコープから子コンポーネントへとデータを渡せるようにできます。
試しに先ほどの例の「見出し」を変えられるようにしてみます。

##子コンポーネントの書き方
```Header.vue
<template>
  <div class="header">
    <h1>会社名</h1>
    <span>{{ title }}</span>
  </div>
</template>

<script>
export default {
  name: 'Header',
  props: {
    title: String
  }
}
</script>

---以下略---
```

`{{ title }}`でtitleにセットされた値を受け取れるようにします。

では実際titleに何をいれるのか？
通常dataにtitleを定義しますが、今回titleに何が入るか決めるのは親でないといけません。そのため親からデータをもらえるよう`props`を使用します。今回は文字列をもらうので`title: String`としています。

###補足１
以下のように書いても同じ動きになります。

```Header.vue
<script>
export default {
  name: 'Header',
  props: {
    title: {
      type: String
    }
  }
}
</script>
```

###補足２
補足１のような書き方をすることで他の項目も定義できます。

```Header.vue
<script>
export default {
  name: 'Header',
  props: {
    title: {
      type: String,
      default: 'デフォルト', //デフォルト値
      required: true //必須
    }
  }
}
</script>
```



##親コンポーネントの書き方

```Index.vue
<template>
  <div id="app">
      <HeaderName title="見出し１"/>
      <HeaderName title="見出し２"/>
  </div>
</template>

<script>
import HeaderName from './components/Header.vue'

export default {
    name: "Index",
    components: {
        HeaderName
    },
}
</script>
```

`title="見出し１"`と渡す値を指定することができます。
わかりやすいように２つ並べてみました。
実行結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/bfd1bb23-b55b-1a36-841e-b1e43858735e.png)

#プロパティに変数を渡す【props + v-bind】
propsで値を受け取れるようにしましたが、固定でなく変数を渡したい場合は以下のようにv-bindを使用します。
子コンポーネントはそのままで問題ありません。親を修正します。

```Index.vue
<template>
  <div id="app">
      <HeaderName title="見出し１"/>
      <HeaderName title="見出し２"/>
      <HeaderName v-bind:title="title"/> --追加
  </div>
</template>

<script>
import HeaderName from './components/Header.vue'

export default {
    name: "Index",
    components: {
        HeaderName
    },
    data() {
        return {
            title: "見出し３",
        }
    },
}
</script>
```

` v-bind:prop名="データ名"`で変数を渡せます。
省略した場合は`:prop名="データ名"`となります。

実行結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/26545bba-5a04-e912-72bf-da1b91694a35.png)

##v-forを使用するとき
v-forでちょっと悩んだので書き方メモ。

###子コンポーネントの書き方

```Header.vue
<template>
  <div>
    <li>{{ menu.name }}</li>
  </div>
</template>

<script>
export default {
  name: 'Header',
  props: {
    menu: Object
    }
}
</script>
```
###親コンポーネントの書き方
```Index.vue
<template>
  <div id="app">
      <Header v-for="menu in menus"
              :key="menu.name"
              :menu="menu"/>
  </div>
</template>

<script>
import Header from './components/Header.vue'

export default {
    name: "Index",
    components: {
        Header
    },
    data() {
        return {
            menus: [
                {
                    name: "メニュー１"
                },
                {
                    name: "メニュー２"
                },
                {
                    name: "メニュー３"
                },
            ]
        }
    },
}
</script>
```



#さいごに
ドキュメントよみながら思い出しながら進めているので補足などあれば随時更新していきます。
また、なにか間違いやこうしたほうがいいよ等何かあればコメントいただけると嬉しいです。
最後まで読んでいただきありがとうございます！