props
を利用して親コンポーネントのデータを受け取ろうとしたが、そのデータがundefined
になり、
ハマったので、その備忘録です。
###親子間のデータ受け渡しについておさらい
まずはコンポーネントにおけるデータの流れについて少しおさらいしようと思います。
Vueでは、親子のコンポーネントの関係は、
props down, events up
というように要約することができます。
親は、 プロパティを経由して、データを子に伝え、子はイベントを経由して、親にメッセージを送ります。
####プロパティによるデータの伝達について
全てのコンポーネントインスタンスは、各自の隔離されたスコープ (isolated scope) を持ちます。
つまり、子コンポーネントのテンプレートで親データを直接参照できない(そしてすべきでない)ということです。
データはプロパティを使用して子コンポーネントに伝達できます。
要するに、すべてのコンポーネントは別々のスコープを持っているので、
子コンポーネントから親コンポーネントのデータを参照することはできないということです。
そのため、データを隔離されたスコープで子コンポーネントに渡すためには、props
オプションを利用する必要があります。
###propsオプションについて
親コンポーネントが持っているデータを子のコンポーネントに受け渡す役割を持ちます。
props
オプションを使って親のデータを受け取るには以下のルールがあります。
####ルールその1
親コンポーネントからデータを受け取るためのプロパティをprops
に書かなくてはなりません。
props
オプションを使うことで、子のコンポーネントはその属性で親のデータを受け取り、そのデータを使えるようになります。
new Vue({
el: '#app',
data: function() {
return {
myMessage: '親が持つメッセージデータ',
}
}
});
Vue.component('child-component', {
props: ['myMessage'],// プロパティを記述
template: '<span>{{myMessage}}</span>'
})
※props
で宣言をしないと、コンポーネント内でそのデータはundefined
になってしまいます。
####ルールその2
props
に追加するだけでは、親から渡されたデータを利用することはできません。
明示的にテンプレートタグにデータをバインディングする必要があります。
<child-component v-bind:my-message="myMessage"></child-component>
先ほど、子のテンプレート内のprops
で記述したプロパティで、親のデータを受け取ります。
#####動的な値(非文字列テンプレート)について
静的な値(文字列テンプレート)をバインディングするケースは少なく、
上記の例のような動的な値をバインディングするケースの方が多いと思います。
その場合は、v-bind
を使用することで属性の値に式が使えるようになります。
親のデータにプロパティを動的にバインディングすることで親でデータが更新される度に、
そのデータが子にも渡るようになります。
-
v-bind
の省略記法を使用すると以下のようにシンプルに書けます。
<child-component :my-message="myMessage"></child-component>
#####プロパティ名について
別のデータに代入しているみたいな感じですが、親と子ではスコープが違うので
プロパティ名は親データと同じでも、下記のように別の名前を使っても大丈夫です。
new Vue({
el: '#app',
data: function() {
return {
myMessage: '親が持つメッセージデータ',
}
}
});
Vue.component('child-component', {
props: ['message'],// プロパティを記述
template: '<span>{{message}}</span>'
})
<child-component :message="myMessage"></child-component>
#####HTML内で動的な値(非文字列テンプレート)を使用する場合の注意点
HTMLの属性は大文字と小文字を区別しません。
そのため、動的な値(非文字列テンプレート)を使用する場合、
バインディングに利用するプロパティ名を属性として使用するときは、
それらをケバブケース (kebab-case: ハイフンで句切り) に変換して記述する必要があります。
キャメルケース:myMessage
ケバブケース:my-message
-
undefined
になる例
<child-component :myMessage="myMessage"></child-component>
- ケバブケース
<child-component :my-message="myMessage"></child-component>
※静的な値(文字列テンプレート)を使用する場合は、この制限は適用されません。
JavaScriptではキャメルケースで書いていても、HTML内ではケバブケースの記法で書かないといけません。
自分はこれで1時間ぐらいハマっていました。。。
ドキュメントに書いてあるのですが、完全に見落としていました。
###参考サイト