概要
React 公式のチュートリアルで紹介されている三目並べゲームを Vue.js で作ってみます。
スターターコードを用意する
チュートリアルではスターターコードが用意されています。
そこには既に 3 つのコンポーネントが作られています。
- Square
- Board
- Game
まずはこれらのコンポーネントを作りましょう。
// app.js
Vue.component("Square", {
template: '<button class="square">{{ /* TODO */ }}</button>',
});
Vue.component("Board", {
data() {
return { status: "Next player: X" };
},
template: `
<div>
<div class="status">{{ status }}</div>
<div class="board-row">
<Square :value="0" />
<Square :value="1" />
<Square :value="2" />
</div>
<div class="board-row">
<Square :value="3" />
<Square :value="4" />
<Square :value="5" />
</div>
<div class="board-row">
<Square :value="6" />
<Square :value="7" />
<Square :value="8" />
</div>
</div>`,
});
Vue.component("Game", {
template: `
<div class="game">
<div>
<Board />
</div>
<div class="game-info">
<div>{{ /* status */ }}</div>
<ol>{{ /* TODO */ }}</ol>
</div>
</div>
`,
});
const app = new Vue({
el: "#app",
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TicTacToe</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="app">
<Game />
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="app.js"></script>
</html>
データを Props を使って渡す
ここからチュートリアル通りやっていきます。
Board から Square へ value プロパティ を props 経由で渡すようコードを変更します。
ここではすでに Board の方では v-bind で値を渡しているので変更の必要はありません。
Square のテンプレートで props を定義し、受け取った値を表示するように書き換えます。
Vue.component("Square", {
props: ["value"],
template: '<button class="square">{{ value }}</button>',
});
9 つのマスに 0 から 8 までの数字が入っていることが確認できます。
イベントハンドラを付け加える
Square コンポーネントがクリックされると、数字のかわりに “X” と表示されるように変更します。
これには Square のボタンタグにイベントハンドラを設定します。
Vue.component("Square", {
props: ["value"],
methods: {
click() {
alert("click");
},
},
template: '<button class="square" @click="click">{{ value }}</button>',
});
こちらではチュートリアルのようにエラーは出ません。
そのかわり、テンプレートでは直接 alert 関数を呼び出せないため、methods プロパティで click 関数を定義しています。
次に、クリックされたマスが “X” で埋められるように変更します。
Square コンポーネントに状態を持たせるため、data に value プロパティを追加します。
そして クリックされたときに value プロパティに “X” がセットされるようにします。
Vue.component("Square", {
data() {
return { value: null };
},
methods: {
click() {
this.value = "X";
},
},
template: '<button class="square" @click="click">{{ value }}</button>',
});
ここまでで、基本的な部分が完成です。
次はターン制や勝敗判定をできるようにしていきます。