1. 事件代理(委托)
可以解决的问题:如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能
基本原理:事件委托是利用事件的冒泡原理来实现的,何为事件冒泡(事件从最深的节点开始,然后逐步向上传播事件)
事件代理的适用场景:应用频繁触发事件时 || 当列表频繁创建删除时
2. 一个简易的扫雷游戏
我是从下面几步来完成的:
(1). 先完成界面的设计(界面的初始方块与初始数组的大小是对应的)
(2). 添加点击事件(利用事件委托)
(3). 完成事件触发调用的函数(在这个过程中需要计算“九宫格”雷区的数目)
(4). 写一个随机生成雷区的函数
界面的样式以及布局
*{
margin : 0;
padding: 0;
}
body {
font-family: "微软雅黑";
font-size: 14px;
background : #615454;
}
.box {
width: 320px;
position: fixed;
left: 50%;
top: 20%;
margin-left: -160px;
background: #fff;
}
.box span{
width: 30px;
height: 30px;
display: block;
border: 1px solid #ddd;
float: left;
background : #b3a157;
cursor: pointer;
text-align: center;
line-height: 30px;
}
.box span.danger{
background: black;
}
.box span.safety{
background: white;
}
<div id="box" class='box'></div>
初始化界面的代码:
controller.draw = function() {
var html = '';
for(var i = 0, len = controller.arr.length; i < len; i++) {
for(var j = 0, len1 = controller.arr[i].length; j < len1; j++) {
html += "<span></span>";
}
html += '<br>';
}
controller.box.innerHTML = html;
}
controller.arr = [
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
];
事件委托的代码
在这里我把span的点击事件委托给div,给div添加了点击事件,通过event对象可以得到鼠标点击的元素,通过event获得点击的位置,计算出发生点击的span横纵坐标,计算出九宫格内的地雷数目并显示
controller.clickEve = function() {
window.addEventListener ? controller.box.addEventListener('click', controller.gover, false) : attachEvent('onclick', controller.gover);
}
controller.gover = function(eve) {
eve = eve || window.event;
var num = 0,
i = 0,
j = 0,
targetElement = eve.target || eve.srcElemeent,
pointerXY = controller.getPointer(eve),
boxOffsetLeft = controller.box.offsetLeft,
boxOffsetTop = controller.box.offsetTop,
relativeLeft = pointerXY.pointerX - boxOffsetLeft,
relativeTop = pointerXY.pointerY - boxOffsetTop;
//x代表行数的下标, y代表列数的下标
i = relativeLeft % 32 == 0 ? Math.floor(relativeLeft / 32 - 1) : Math.floor(relativeLeft / 32);
j = relativeTop % 32 == 0 ? Math.floor(relativeTop / 32 - 1) : Math.floor(relativeTop / 32);
if(controller.arr[i][j] == 1) {
targetElement.className = 'danger';
setTimeout(function() {
alert('游戏结束');
controller.random();
controller.draw();
}, 300);
}else {
for(x = i-1; x <= i+1; x++) {
for(y = j-1; y <= j+1; y++) {
if(x < 0 || y < 0 || x > controller.arr.length-1 || y > controller.arr.length-1) {
continue;
}
if(controller.arr[x][y] == 1) {
num++;
}
}
}
targetElement.className = 'safety';
targetElement.innerText = num ? num : "";
}
}
出现的效果:
整个的JS代码如下,最下面的注释解释了计算九宫格雷的数目的思路:
var controller = function() {}
controller.box = document.getElementById('box');
controller.draw = function() {
var html = '';
for(var i = 0, len = controller.arr.length; i < len; i++) {
for(var j = 0, len1 = controller.arr[i].length; j < len1; j++) {
html += "<span></span>";
}
html += '<br>';
}
controller.box.innerHTML = html;
}
controller.arr = [
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
];
controller.gover = function(eve) {
eve = eve || window.event;
var num = 0,
i = 0,
j = 0,
targetElement = eve.target || eve.srcElemeent,
pointerXY = controller.getPointer(eve),
boxOffsetLeft = controller.box.offsetLeft,
boxOffsetTop = controller.box.offsetTop,
relativeLeft = pointerXY.pointerX - boxOffsetLeft,
relativeTop = pointerXY.pointerY - boxOffsetTop;
//x代表行数的下标, y代表列数的下标
i = relativeLeft % 32 == 0 ? Math.floor(relativeLeft / 32 - 1) : Math.floor(relativeLeft / 32);
j = relativeTop % 32 == 0 ? Math.floor(relativeTop / 32 - 1) : Math.floor(relativeTop / 32);
if(controller.arr[i][j] == 1) {
targetElement.className = 'danger';
setTimeout(function() {
alert('游戏结束');
controller.random();
controller.draw();
}, 300);
}else {
for(x = i-1; x <= i+1; x++) {
for(y = j-1; y <= j+1; y++) {
if(x < 0 || y < 0 || x > controller.arr.length-1 || y > controller.arr.length-1) {
continue;
}
if(controller.arr[x][y] == 1) {
num++;
}
}
}
targetElement.className = 'safety';
targetElement.innerText = num ? num : "";
}
}
controller.clickEve = function() {
window.addEventListener ? controller.box.addEventListener('click', controller.gover, false) : attachEvent('onclick', controller.gover);
}
controller.getPointer = function(event) {
var pointerXY = {
pointerX : event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)),
pointerY : event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))
}
return pointerXY;
}
controller.random = function() {
for(var i = 0; i < controller.arr.length; i++) {
for(var j = 0; j < controller.arr.length; j++) {
controller.arr[i] = controller.arr[i].sort(function(){
return 0.5-Math.random(); // 0-1 从小到大或者从小到大
});
}
}
}
//i-1: j-1 i-1 : j i-1: j+1
//i : j-1 点击处 i : j+1
//i+1: j-1 i+1 : j i+1: j+1
所写内容如有不足,欢迎指正