Vue.jsでは、propsと$emitを使用して、親コンポーネントと子コンポーネントの間でデータをやり取りします。
子コンポーネント側にpropsで定義したプロパティには、親コンポーネント側でv-bindディレクティブを使用してデータをバインドします。
子コンポーネント側で$emitを使用して発行したイベントには、親コンポーネント側でv-onディレクティブを使用してメソッドや式をバインドします。
本記事では、propsに定義したプロパティと$emitで定義したイベントを、親コンポーネントのv-bindディレクティブ、v-onディレクティブでバインドしてデータをやり取りする方法について紹介します。
子コンポーネントの実装
子コンポーネント側の実装例を示します。
ここでは簡単な例として、type属性にnumberを指定したinput要素を子コンポーネントに配置します。
1 2 3 4 5 6 |
<script type="text/x-template" id="custom-component"> <input type="number" v-bind:value="numberValue" v-on:input="onInput"/> </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const inputNumber = { template: '#custom-component', props: { numberValue: { type: String, default: '', required: true } }, methods: { onInput: function(e) { this.$emit('number-input', e.target.value) } } } |
子コンポーネントでは、input要素にv-bindディレクティブでpropsに定義したnumberValueプロパティをバインドします。(HTMLの4行目)
v-onディレクティブでinput要素のinputイベントにメソッドをバインドし、メソッドでは$emitで「number-input」イベントを発行します。
「number-input」イベントを発行する$emitでは、引数にinput要素のvalueを指定します。(JavaScriptの12行目)
ここで指定した第2引数のデータを親コンポーネント側で受け取ります。
親コンポーネント(アプリケーション)の実装
親コンポーネント側の実装例を示します。
親コンポーネントでは、子コンポーネントをHTMLテンプレートに配置し、子コンポーネントにバインドしたデータを表示するためのdiv要素を配置します。
1 2 3 4 5 6 7 |
<div id="app"> <input-number v-bind:number-value="value" v-on:number-input="value = $event"></input-number> <div> {{value}} </div> </div> |
1 2 3 4 5 6 7 8 9 10 |
Vue.createApp({ components: { 'input-number': inputNumber }, data: function() { return { value: 0 } } }).mount('#app') |
親コンポーネントでは、dataオプションに定義したvalueプロパティのデータ(JavaScriptの7行目)を子コンポーネント(input-number)で定義したpropsの「number-value」にv-bindディレクティブでバインドします。(HTMLの2行目)
子コンポーネントで発行したnumber-inputイベントをv-onディレクティブでバインドし「value = $event」を指定することにより、dataオプションに定義したvalueプロパティのデータを、子コンポーネントの$emitで指定した引数の値で更新します。(HTMLの3行目)
実行結果
上記のソースを実行すると以下のようなが画面が表示され、親コンポーネントと子コンポーネント間でデータが同期していることが確認できます。
Vue.jsでの親子コンポーネント間でのデータのやり取りは、「Props down, Event up」が基本ですので、上記の方法でデータをやり取り(同期)することができますが、Vue.jsでは、データを同期する方法としてv-modelディレクティブの実装があります。
次回は、親コンポーネントでv-modelディレクティブを使用して子コンポーネントとデータをやりとりするするための、子コンポーネントの実装について紹介します。