「Vue.js」の「コンポーネント間の通信」を学ぶ
「コンポーネント」は少しずつ理解が進んできましたが、「コンポーネント間でのデータの受け渡しはどうすればいいのか?」という疑問が浮かんできました。
「コンポーネント」は「UI部品」と考えると「データの共有」が重要になってくるのではないかと思っています。
今回は「コンポーネント間のデータのやり取り」について学んでいきたいと思います。
「親」から「子」のコンポーネントへデータを渡す方法
前回の「コンポーネント」の学習でも触れましたが、さらにプログラムを作って理解を進めていきたいと思います。
「props」を利用することで、「親」から「子」のコンポーネントへデータを渡すことができました。
「子コンポーネント」に「props」を定義することで、「親コンポーネント」から「子コンポーネント」へデータを渡すことができます。
前回とは異なって「データリスト」を「子コンポーネント」へ渡して「リスト形式」で表示をしてみたいと思います。
プログラムを作ってみると、
<div id="app"> <parent-comp></parent-comp> </div> <script> const childComp = { props: ['id', 'name', 'price'], template: '<li>「{{ name }}」は{{ price }}円です。</li>' } Vue.component('parent-comp', { template: '<ul><child-comp v-for="item in items" v-bind:id="item.id" v-bind:name="item.name" v-bind:price="item.price" :key="item.id"></child-comp></ul>', components: { 'child-comp': childComp }, data: function () { return { items: [ { id: 1, name: '唐揚げ定食', price: 880 }, { id: 2, name: '焼肉定食', price: 980 }, { id: 3, name: '牛丼', price: 520 }, { id: 4, name: 'カツカレー定食', price: 920 }, { id: 5, name: 'すき焼き定食', price: 980 }, ] } } }) let app = new Vue({ el: '#app' }) </script>
のようになります。このプログラムを実行すると、
→「Vue.jsプログラムの実行(コンポーネントのデータ渡し(親→子))」
のようになります。
「v-for」で繰り返し処理を行っていますが、渡すデータを「v-bind」で1つずつ指定しないといけないため、「渡すデータの種類」が増えると「コードを書く量」も増え、可読性も下がってしまいます。
あと、「for文」のところでも登場しましたが、「:key」を書かないと、「コンソール」に「key」を指定するようメッセージが表示されます。
「子」から「親」のコンポーネントへデータを渡す方法
「子のコンポーネント」から「親のコンポーネント」にデータを渡す場合は、下記のようになります。
<div id="app"> <parent-comp></parent-comp> </div> <script> const childComp = { props: ['id', 'name', 'price'], template: '<li>「{{ name }}」は{{ price }}円です。<button v-on:click="selectItem" v-bind:id=id>購入</button></li>', methods: { selectItem: function (e) { this.$emit('clickItem', e.target.id); } } } Vue.component('parent-comp', { template: '<ul><child-comp v-on:clickItem="displayItem" v-for="item in items" v-bind:id="item.id" v-bind:name="item.name" v-bind:price="item.price" :key="item.id"></child-comp></ul>', components: { 'child-comp': childComp }, data: function () { return { items: [ { id: 1, name: '空気清浄機', price: 12980 }, { id: 2, name: '加湿器', price: 2980 }, { id: 3, name: '扇風機', price: 1980 }, ] } }, methods: { displayItem: function (itemId) { const itemName = this.items[itemId]['name'] + '(' + this.items[itemId]['price'] + '円)'; alert(`${itemName}が選択されました。`); } } }) let app = new Vue({ el: '#app' }) </script>
のようになります。このプログラムを実行すると、
→「Vue.jsプログラムの実行(コンポーネントのデータ渡し(子→親))」
のようになります。
仕組みが複雑なので図を作成してみると、
のようになります。
まず「子コンポーネントのボタン」がクリックされると、「selectItemメソッド」が実行されます。
「子コンポーネント」は、
<button v-on:click="selectItem" v-bind:id=id>購入</button>
のように、「v-on」によって「クリック」されると「子コンポーネント」の「selectItemメソッド」が実行されるよう設定しています。
「selectItemメソッド」では、
selectItem: function (e) { this.$emit('clickItem', e.target.id); }
のように「$emit」が実行されます。
「$emit」は「子コンポーネント」の「ボタンクリック」などのイベントを「親コンポーネント」に伝達することができます。
「第二引数」に「親コンポーネントに渡したい値」を設定すると「親コンポーネント」に値を渡すこともできます。
「親要素」の「template」では、
<child-comp v-on:clickItem="displayItem" v-for="item in items" v-bind:id="item.id" v-bind:name="item.name" v-bind:price="item.price" :key="item.id"></child-comp>
のように「$emit」によって送られた「子コンポーネント」の「clickItem」を検知すると「親コンポーネント」の「displayItemメソッド」を実行するように設定しています。
そして「displayItemメソッド」の「商品情報を表示する処理」が実行されます。
今回は「コンポーネント間の値の渡し方」について学んでいきましたが、プログラムを書いていて「かなり複雑な仕組み」だと感じたので、繰り返しプログラムを書いていかないと忘れてしまいそうです。
難しさを感じる仕組みですが、繰り返し学びながら少しずつ理解していきたいと思います。