理系公務員のプログラミング日記

Vue3で○×ゲームを作る②

タグ:
vue3

子から親にクリックイベントが発火したことを伝える

親コンポーネントで管理しているcount変数を増加させるタイミングは、子コンポーネントでクリックイベントが発火したときです。

子コンポーネント内でクリックイベントにv-onで紐付いているdoAction内で$emitを使い、
親で管理するcountを増加させるイベントであるdoCountUpを実行してもらいます。

$emitについて教科書では説明不足なので補足すると、
this.$emit(親に登録したイベント名,(必要なら)親に渡す引数1,引数2,・・・)
という形で使用します。

ついでに、一度クリックした箇所は選ばせないようにし、三項演算子を使って○×の判定を簡潔にします。

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>

今回は引数は付けずに親のイベントcount-eventのみを動作させるものとしました。
親側ではこれをv-ondoCountUpと紐付かせています。

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属性が付いているのが分かります。

vue-dev-tool

このkeyに渡した"n"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); }, // 略

続きます