【Vue.js】propsで子コンポーネントにデータが渡らないのはHTMLの命名規則が原因だった

`props`を利用して親コンポーネントのデータを受け取ろうとしたが、そのデータが`undefined`になり、
ハマったので、その備忘録です。


###親子間のデータ受け渡しについておさらい

まずはコンポーネントにおけるデータの流れについて少しおさらいしようと思います。
>Vueでは、親子のコンポーネントの関係は、`props down, events up`というように要約することができます。
>親は、 プロパティを経由して、データを子に伝え、子はイベントを経由して、親にメッセージを送ります。

![props-events.png](https://qiita-image-store.s3.amazonaws.com/0/140727/a74dfad5-ef48-2ccd-290d-295bd6bae52c.png)


####プロパティによるデータの伝達について
>全てのコンポーネントインスタンスは、各自の隔離されたスコープ (isolated scope) を持ちます。
>つまり、子コンポーネントのテンプレートで親データを直接参照できない(そしてすべきでない)ということです。
>データはプロパティを使用して子コンポーネントに伝達できます。

要するに、すべてのコンポーネントは別々のスコープを持っているので、
子コンポーネントから親コンポーネントのデータを参照することはできないということです。

そのため、データを隔離されたスコープで子コンポーネントに渡すためには、`props`オプションを利用する必要があります。

###propsオプションについて

親コンポーネントが持っているデータを子のコンポーネントに受け渡す役割を持ちます。
`props`オプションを使って親のデータを受け取るには以下のルールがあります。



####ルールその1
親コンポーネントからデータを受け取るためのプロパティを`props`に書かなくてはなりません。
`props`オプションを使うことで、子のコンポーネントはその属性で親のデータを受け取り、そのデータを使えるようになります。

```javascript:親コンポーネント
new Vue({
	el: '#app',
	data: function() {
		return {
			myMessage: '親が持つメッセージデータ',
		}
	}
});
```


```javascript:子コンポーネント
Vue.component('child-component', {
	props: ['myMessage'],//　プロパティを記述
	template: '<span>{{myMessage}}</span>'
})
```
※`props`で宣言をしないと、コンポーネント内でそのデータは`undefined`になってしまいます。




####ルールその2
`props`に追加するだけでは、親から渡されたデータを利用することはできません。
明示的にテンプレートタグにデータをバインディングする必要があります。

```html:HTML
<child-component v-bind:my-message="myMessage"></child-component>
```
先ほど、子のテンプレート内の`props`で記述したプロパティで、親のデータを受け取ります。

#####動的な値（非文字列テンプレート）について
静的な値（文字列テンプレート）をバインディングするケースは少なく、
上記の例のような動的な値をバインディングするケースの方が多いと思います。
その場合は、`v-bind`を使用することで属性の値に式が使えるようになります。
親のデータにプロパティを動的にバインディングすることで親でデータが更新される度に、
そのデータが子にも渡るようになります。

- `v-bind`の省略記法を使用すると以下のようにシンプルに書けます。

```html:HTML
<child-component :my-message="myMessage"></child-component>
```

#####プロパティ名について
別のデータに代入しているみたいな感じですが、親と子ではスコープが違うので
プロパティ名は親データと同じでも、下記のように別の名前を使っても大丈夫です。

```javascript:親コンポーネント
new Vue({
	el: '#app',
	data: function() {
		return {
			myMessage: '親が持つメッセージデータ',
		}
	}
});
```


```javascript:子コンポーネント
Vue.component('child-component', {
	props: ['message'],//　プロパティを記述
	template: '<span>{{message}}</span>'
})
```

```html:HTML
<child-component :message="myMessage"></child-component>
```

#####HTML内で動的な値（非文字列テンプレート）を使用する場合の注意点
**HTMLの属性は大文字と小文字を区別しません。**
そのため、動的な値（非文字列テンプレート）を使用する場合、
バインディングに利用するプロパティ名を属性として使用するときは、
それらをケバブケース (kebab-case: ハイフンで句切り) に変換して記述する必要があります。

キャメルケース：`myMessage`
ケバブケース：`my-message`

- `undefined`になる例

```html:HTML
<child-component :myMessage="myMessage"></child-component>
```

- ケバブケース

```html:HTML
<child-component :my-message="myMessage"></child-component>
```

※静的な値（文字列テンプレート）を使用する場合は、この制限は適用されません。

JavaScriptではキャメルケースで書いていても、HTML内ではケバブケースの記法で書かないといけません。
自分はこれで1時間ぐらいハマっていました。。。
[ドキュメント](https://jp.vuejs.org/v2/guide/components.html#%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9-vs-%E3%82%B1%E3%83%90%E3%83%96%E3%82%B1%E3%83%BC%E3%82%B9)に書いてあるのですが、完全に見落としていました。


###参考サイト

- [Vue.jsでcomponentsに親からデータがわたらない時に確認する2つのこと](http://www.ie-kau.net/entry/2016/02/13/_Vue.js%E3%81%A7components%E3%81%AB%E8%A6%AA%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8C%E3%82%8F%E3%81%9F%E3%82%89%E3%81%AA%E3%81%84%E6%99%82%E3%81%AB%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B2%E3%81%A4)