前一節完成了掃雷的基本功能:翻開雷區以及標記為雷。在這一節,就到獲取遊戲結果的時候了。
有個問題,我們之前的翻開雷區以及標記為雷都是在 Square 組件中實現的,但是遊戲結果需要 Board 組件來統計,咋整呢? 這時候就需要用到事件傳遞了。
組件的事件傳遞
在 Vue 中,父子組件中經常會傳遞事件;在此,也僅僅會涉及到父組件接收子組件傳遞的事件。
若欲瞭解更多事件相關信息,請查閱文檔的事件以及事件總線
子組件通過 this.$emit('event-name', payload, ...) 向父組件發事件,父組件通過在調用子組件時的 @event-name="eventHandler" 來接收並處理事件。
其中,event-name 是事件的名稱,payload 是事件的負載(可以是任何類型的數據), $emit 方法在事件名後,可以傳遞多個參數,此時,在 eventHandler 函數上會接收到相同數量的參數。
所以,對 Square 組件進行一些改動,以將翻開與標雷事件傳遞給 Board 組件:
發出事件
Square.vue
export default {methods: {
onLeftClick() {
if (this.clipped || this.marked) {
return;
}
this.clipped = true;
if (this.data.mine) {
// 當前是雷時,觸發爆炸事件
this.$emit("exploded");
} else {
// 當前不是雷時觸發翻開事件
this.$emit("clipped");
}
},
onRightClick() {
// 切換插旗
this.marked = !this.marked;
this.$emit("marked", this.marked);
}
}
}
此時,一共觸發了三個事件:
- exploded 當翻開雷區時遇到雷觸發
- clipped 當翻開雷區時未遇到雷觸發
- marked 當插上旗後觸發
接收事件
Board.vue
<template>
雷數量: {{mineCount}}, 已標記: {{markCount}},剩下: {{mineCount - markCount}}
<table>
<square>
/<table>
{{result}}
/<template>
在 Board 組件中,接收了三個事件 @clipped="onClipped" @exploded="onExploded" @marked="onMarked"。另外添加了一個 div.result 用於顯示遊戲結果。
在遊戲面板上方,添加了雷數量統計信息的展示。
新增加了一個計算屬性 remainSquares,用於計算剩下未翻開並且未插旗的雷區,當此值為0時,表示遊戲通關。
this.size ** 2 表示雷區總數量。另外,新增了一個監視器 remainSquares,以監視其值的變化,在變化時,判斷遊戲是否通關。
- 當翻開雷時,會觸發 exploded 事件,此時會設置 result 的值,此時為遊戲失敗
- 當已經翻開和標記塊之和等於總數時,,此時為遊戲通過
全完
總結
回顧這個小遊戲的開發,已經介紹了以下內容:
- 使用 Vue cli 創建項目
- Vue 組件的結構
- Vue 模板以及語法
- Vue 事件傳遞
- Vue 計算屬性
- Vue 監視器
而 Vue 遠不只是如此,還有很多有意思的東西,等你去玩。當然,這個小遊戲也不只如此,它還有一個更加完整的版本,存放在 https://gitee.com/hyjiacan/mine-sweeper 的 full 分支上,有興趣的朋友可以移步查看源碼。
祝各位朋友在前端的坑裡,越滑越深!!
閱讀更多 前端小李 的文章