上一节已经画出了雷区,并且按位置放置好了雷,那么这一节,就要开始交互处理了。 但是,细细一想,在扫雷游戏中,每个雷区都会有遮罩(mask)、雷、旗、问号等显示,并且需要处理鼠标的左/右键的点击事件,相对来说,这算一个比较复杂的功能了。既然如此,就新写一个组件 Square.vue 吧。 此时,我使用了 Less 样式,需要先安装 Less 支持 yarn add less less-loader -D,对应的 npm 命令为 npm install less less-loader --save-dev 效果如下 现在来说明一下此组件中用到的东西: 在 Board.vue 中引用: 到现在,就有了简单的鼠标交互了,此时点击雷区就能翻开指定块了。 回想一下扫雷这个游戏,还需要通过鼠标右键来将某个区标记为雷(插旗),所以我们需要再给组件加上鼠标的右键事件,此时,就可以对组件进行一些改造使其能同时响应鼠标的左右键事件,模板如下: Square.vue 效果如图 继续解释一下新增加的部分: 到此,扫雷的基本功能就完成了。 本节完 雷区
Square.vue
<template>
<div class="square" :class="computedClass" @click="onClick">
<span class="text" v-if="clipped && square.mine">雷</span>
<span class="text" v-if="clipped && !square.mine">{{square.count}}</span>
</div>
</template>
<script>
export default {
name: "Square",
props: {
data: {
type: Object,
required: true
}
},
data() {
return {
// 标记此区是否已经被翻开
clipped: false
};
},
computed: {
// 自动计算样式
computedClass() {
return {
clipped: this.clipped
};
},
square() {
return this.data || {};
}
},
methods: {
onClick() {
this.clipped = true;
}
}
};
</script>
<style lang="less" scoped>
.square {
display: block;
height: 30px;
line-height: 30px;
width: 30px;
text-align: center;
background-color: burlywood;
/* 设置鼠标动作交互 */
&:hover {
background-color: lightblue;
}
}
.clipped,
.clipped:hover {
background-color: #ffffff;
}
</style>
<template>
<div class="board">
<table>
<tr v-for="(row, rowIndex) in data" :key="rowIndex">
<td v-for="cell in row" :key="cell.col">
<square :data="cell" />
</td>
</tr>
</table>
</div>
</template>
<script>
import Square from './Square'
export default {
// 此处省略了之前已经写好的代码
components: { Square }
}
</script>
插旗标记
<template>
<div
class="square"
:class="computedClass"
@click.left="onLeftClick"
@click.right.prevent="onRightClick"
>
<span class="text" v-if="clipped && square.mine">雷</span>
<span class="text" v-if="clipped && !square.mine">{{countText}}</span>
</div>
</template>
<script>
// 省略了已经写好的部分
export default {
data() {
return {
// 标记是否已经插上了旗
flagged: false
};
},
computed: {
countText() {
return this.data.count ? this.data.count : "";
}
},
methods: {
onLeftClick() {
if (this.clipped || this.flagged) {
return;
}
this.clipped = true;
},
onRightClick() {
this.flagged = !this.flagged;
}
}
};
</script>
<style lang="less" scoped>
.flagged {
&:after {
content: "旗";
background-color: red;
color: white;
padding: 1px 3px;
font-size: 12px;
}
}
</style>