Vue3で○×ゲームを作る②
タグ:
vue3
子から親にクリックイベントが発火したことを伝える
親コンポーネントで管理しているcount変数を増加させるタイミングは、子コンポーネントでクリックイベントが発火したときです。
子コンポーネント内でクリックイベントにv-on
で紐付いている$emit
を使い、
親で管理するcountを増加させるイベントである
$emitについて教科書では説明不足なので補足すると、
という形で使用します。
ついでに、一度クリックした箇所は選ばせないようにし、三項演算子を使って○×の判定を簡潔にします。
components/Masu.vue
<template> <div class="masu" v-on:click="doAction"> {{ masu }} </div> </template> <script> export default { name: "Masu", data() { return { masu: "", }; }, props: { count: Number, }, methods: { doAction() { if(this.masu === "" ){ this.masu = this.count % 2 === 0 ? "◯" : "×" this.$emit('count-event') } }, }, }; </script>
今回は引数は付けずに親のイベント
親側ではこれをv-on
で
App.vue
<template> <div class="board"> <Masu v-bind:count="count" v-for="n of 9" v-bind:key="n" v-on:count-event="doCountUp" /> </div> </template> <script> import Masu from "./components/Masu.vue"; export default { name: "App", data() { return { count: 0, }; }, components: { Masu, }, methods: { doCountUp() { this.count += 1; }, }, }; </script>
子のどのコンポーネントがクリックされたのかの情報を持たせる
子のコンポーネントを9個作るときに、v-for
を利用しました。その際にkey属性
を設定しています。
公式:key 属性 | Vue.js
key属性はvueのシステム側のアルゴリズムで必須とされる属性で、コンポーネントを並べる順番などに利用されています。
vue.js-devtoolで覗くと、for文で作った子のコンポーネントにkey属性が付いているのが分かります。
このkeyに渡したprops
として子のコンポーネントに渡してあげることで、
各コンポーネントで自身の番号を扱えそうです。
App.vue
<template> <div class="board"> <Masu v-bind:count="count" v-for="n of 9" v-bind:key="n" v-bind:number="n" v-on:count-event="doCountUp" /> </div> </template> // 略
components/Masu.vue
// 略 <script> export default { name: "Masu", data() { return { masu: "", }; }, props: { count: Number, number: Number, }, methods: { doAction() { console.log(this.number) if(this.masu === "" ){ this.masu = this.count % 2 === 0 ? "◯" : "×" this.$emit('count-event') } }, }, }; </script>
クリックされた子の番号と○×の情報を親に送る
components/Masu.vue
$emit
を使い、親のコンポーネントにクリックされたコンポーネント自身の番号とその時の○×の情報を送ってもらいます。
// 略 methods: { doAction() { console.log(this.number) if(this.masu === "" ){ this.masu = this.count % 2 === 0 ? "◯" : "×" // 親のコンポーネントにnumberとmasuの二つの要素を送っている this.$emit('count-event',this.number ,this.masu,) } }, }, };
親でこの情報を受け取ります。
App.vue
// 略 // 子のコンポーネントから受け取った二つのデータ(引数は名前ではなく順序で対応する) // numberとすると名前が被るので、clickNumberとした doCountUp(clickNumber, masu) { this.count += 1; console.log(this.clickNumber); console.log(this.masu); }, // 略
続きます