【Vue.js基礎第2回】コンポーネント基礎・データの渡し方

##はじめに
Vue.jsの基礎について複数回に渡ってまとめていきます(自分用メモ)。今回は「コンポーネント基礎」・「コンポーネント間のデータ渡し」についてです。※内容は初学者向け

【第1回】環境構築・ディレクティブ：https://qiita.com/tatsuya_1995/items/13478027539b7db76e06
<font color="red">【第2回】コンポーネント基礎・データの渡し方(今回)</font>

##基本概念
・Vue.jsは「小さく、自己完結的で再利用可能なコンポーネント」の組み合わせで大規模アプリケーションを構築する。
・「コンポーネント」は予め定義されたオプションを持つVueインスタンス。
・Vueインスタンスを利用するために、「グローバル登録」や「ローカル登録」を行う。
※コンポーネントは構成要素や部品という意味。

##コンポーネントのグローバル登録

```
Vue component('<コンポーネント名>',{<オブジェクト>})
```

①第1引数にコンポーネントの名前、第2引数にオブジェクトとしてコンポーネントの情報を持つ。
②コンポーネントのdataを使う時は関数を使う。

【使用例】

```.js
Vue.component('first-component',{
	data: function() {
  	return	{
   		message : '今日も良い天気！'
  	}
  },
  template: '<p>おはよう！{{ message }}</p>'
})
new Vue({
	el:'#app',
})
```

```.html
<div id="app">
  <first-component></first-component>
  <first-component></first-component>
</div>
```

【表示】
![component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/b0603db3-393f-87b7-b0a8-c206dc09d302.png)

###（NG例①）コンポーネントを使わずに再利用しようとした場合
【使用例】

```.js
new Vue({
	el:'.app',
  data: {
  	message : '今日も良い天気！'
  },
  template: '<p>おはよう！{{ message }}</p>'
})
```

```.html
<div class="app">
</div>
<div class="app">
</div>
```
class属性として`app`は２箇所に記述されているが、初めの`app`しか表示されない。

【表示】
![classApp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/c6a10a9e-502c-1e81-463a-799d8523352b.png)






###(NG例②)コンポーネントのデータを関数として取得しなかった場合
【使用例】

```.js
Vue.component('first-component', {
	data: {
    	count: 0
    },
   template: '<p>カウントアップ({{ count }})<button @click="count += 1">+1</button></p>'
})

new Vue({
	el:'#app'
})
```

コンポーネント内のデータを関数にしないとバグが発生。()内の数字が表示されず、clickイベントも発火しない。
【表示】
![bug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/bb13500c-2fcb-d49e-4f25-0e5415387602.png)


##コンポーネントのローカル登録
①データをオブジェクトとして変数へ代入。
②Vueインスタンスを生成し、`components`オプションにコンポーネント名と変数名を記述。

```.js
//定義
var <変数名> = {<オブジェクト>}

//Vueインスタンスの生成
new Vue({
   components:{
     '<コンポーネント名>' : <変数名>
   }
})
```

【使用例】

```.js
//定義
var component = {                         
    data: function(){
        return {
          count:0
        } 
    },
     template: '<p>カウントアップ({{ count }})<button @click="count += 1">+1</button></p>'
}
//オプション
new Vue({
	el:'#app',
    components:{                           
  	  'first-component': component
    }
})
```

```.html
<div id="app">
  <first-component></first-component>
</div>
```
【表示】
![local.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/701db56e-64c5-d828-3962-74d95482c83c.png)

##Vue CLI
以降、Vue CLIを使って開発を進める。
>CLIはCommnad Line Interfaceの略で、コマンドラインを使ってvue.jsで開発を行うための前準備を支援してくれるツールです。Vue CLIを使ってプロジェクトの作成を行う際、プロジェクトで利用する機能のインストールも一緒に行うことができます。

参考:Vue CLI
https://reffect.co.jp/vue/finally-understand-vue-cli


##単一ファイルコンポーネント
 Vue CLIでプロジェクトを作成すると、拡張子がvueとなっている単一ファイルコンポーネントが作られる。HTMLにより見た目を構成するtemplate、データ定義や処理を定義するscript、スタイルを定義するstyleの3つで構成される。

【基本構成】

```.vue
<template>
  //htmlの記述
</template>

<script>
  //JavaScriptの記述
</script>

<style>
  //CSSの記述
</style>
```
参考：単一ファイルコンポーネント
https://b1tblog.com/2019/10/03/vue-button/

##コンポーネント間でデータを受け渡す

###親コンポーネントから子コンポーネントへ

①親コンポーネント内に属性として子コンポーネントをいれる
②子コンポーネント内に`props: ['<親から受け取るデータ名>']`を記述※
③`<template>`に親から受け取ったデータ名をマスタッシュ`{}`内に記述
※props:は配列ではなく、オブジェクトとしても記述可能

【使用例】 親コンポーネント`App.vue`、子コンポーネント`Counter.vue`

```App.vue
<template>
  <div>
    <p>親から子へ送る値({{ number }})</p>
    <Counter :number="number" ></Counter>
  </div>
</template>
<script>

export default {
  data() {
    return {
      number: 10       //10を子コンポーネントへ送る
    } 
  },
  components: {
    Header
  }
}
</script>
```

```Counter.vue
<template>
    <div>
        <p>受け取った値の半分（{{ number / 2}}）</p>
    </div>
</template>

<script>
export default {
    props: ['number']   //親コンポーネントから受け取る
};
</script>
```
【表示】
![component.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/914d8f5d-b3bc-d4ad-1374-0cd3486c16a0.png)



参考：props
https://jp.vuejs.org/v2/api/#%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3-%E3%83%87%E3%83%BC%E3%82%BF

###子コンポーネントから親コンポーネントへ

①`$emit`：子コンポーネントの好きなタイミングで親コンポーネントのカスタムイベントを発火できるメソッド。この第2引数に値を入れることで親コンポーネントへ渡す。
②親コンポーネントは`$event`で受け取る。

【使用例】 親コンポーネント`App.vue`、子コンポーネント`Number.vue`

```App.vue
<template>
  <div>
    <h2>{{ number }}</h2>
    <Number :total-number="number" v-on:click="number = $event"></Number>
  </div>
</template>
```



```.Number.vue
<template>
    <div>
        <p>いいね（{{ halfNumber }}）</p>
        <button @click="increment">+1</button>
    </div>
</template>

<script>
export default {
    props: {
        totalNumber : {
            Number,
            default: 8
        }
    },
    computed: {
        halfNumber() {
            return this.totalNumber /2 ;
        }
    },
    methods: {
        increment(){
            this.$emit('click',this.totalNumber + 1);
        }
    }
};
</script>
```
##最後に
Vueの「コンポーネント基礎」・「データの渡し方」についてまとめました。複数回に渡ってVueの基礎をまとめていきます。
（もしこの記事に誤りがありましたらご教授いただけると幸いです。）