一、 任务情况:
1. 任务效果

2. 伪代码,主要为了提高代码可读性,并整理好程序运行思路,通过简单、易懂的方式来给他人阅读理顺;
① 对于简单的程序一般不需要写流程,主要对于复杂的程序即算法,通过伪代码来理清算法如何运行;
② 看了格式规范还是没有弄得明白,而且又要放在注释里面才不出错,感觉还是要以简单易懂为主,这次当作练习来理清自己的思路所用;
二、 任务细节:
1. 定义一个专属于九宫格页面的全局对象,避免过多的变量和函数放在document对象里面,也方便统一一个命名空间来维护;

① 获取三个DOM节点,和声明一个储存定时器的对象
var nineBoxs = {
boxsList: document.getElementById("nineBoxs").getElementsByClassName("box"),
btnStart: document.getElementById("start"),
btnEnd: document.getElementById("end"),
// 获取document的Dom树中的box类名的元素节点,以及两个按钮的元素节点
② 声明一个颜色随机的函数,作为方法
colorRandom: function() {
var thisColor = "#";
for (var i = 0; i < 6; i++) {
thisColor += ((Math.random() * 16) | 0).toString(16);
} // 通过随机十六进制的每个字符,来实现十六进制颜色的随机
if (thisColor !== "#ffa600") {
return thisColor;
} else {
return this.colorRandom();
} // 定义输出值与原本颜色不相等
},
// 声明颜色随机的函数
③ 再声明一个位置随机的函数,在位置随机的同时,传递颜色随机函数的值;
boxRandom: function() {
var a = Math.floor(Math.random() * 9),
b = Math.floor(Math.random() * 9),
c = Math.floor(Math.random() * 9);
if ((a - b) * (a - c) * (b - c)) {
// 根据以上乘积不等于0,得a、b、c互不相等,若等于0或NaN,则是false
this.boxsList[a].style.backgroundColor = this.colorRandom();
this.boxsList[b].style.backgroundColor = this.colorRandom();
this.boxsList[c].style.backgroundColor = this.colorRandom();
// 由于该数组的项比较少,所以展开循环来提高性能
console.log(a, b, c); // 方便打印显示来查看随机数字
} else {
this.boxRandom();
} // 定义输出的数组内,每个项的位置互不相等
},
// 声明位置随机的函数
④ 声明一个恢复原本颜色的函数;
boxRecover: function() {
for (i = 0; i < this.boxsList.length; i++) {
this.boxsList[i].style.backgroundColor = "#ffa600";
}
},
// 声明颜色恢复的函数,多用length属性,防止数组越界而报错
};
// 创建一个全局对象,把该页面的变量和函数放在其中,以免与其他全局变量混合而影响调用
⑤ 设置颜色变化的顺序函数,以及一个定时器的对象,一个按钮的开关变量;
bgColorChange: function() {
nineBoxs.boxRecover();
nineBoxs.boxRandom();
},
// 先恢复原本颜色,再应用随机颜色,确保重复调用时保证只有三个随机颜色
intervalId: {},
// 声明一个定时器的对象
btnDisabled: true,
// 设置按钮的开关变量
};
// 创建一个全局对象,把该页面的变量和函数放在其中,以免与其他全局变量混合而影响调用
2. 设置一个“开始闪”按钮的点击事件,实现按钮变色且九宫格随机变色的效果,并赋予定时器,来每秒调用一次变化组合方法,同时所设置的btnDisabled变量,通过变化布尔值,来防止按钮重复点击触发click事件,适用于只需点击一次;
nineBoxs.btnStart.onclick = function() {
if (!nineBoxs.btnDisabled) {
nineBoxs.btnDisabled = true;
// 防止重复点击来重复调用click事件处理程序
this.className = "start-flicker btn-active";
nineBoxs.btnEnd.className = "end-flicker btn-hover";
// 点击后按钮变色,采用更改类名,来尽量给JS/CSS解耦
nineBoxs.intervalId = setInterval(nineBoxs.bgColorChange, 1000);
// 设置间歇调用;
}
};
// 点击后,九宫格随机变色
3. 设置一个“结束闪”按钮的点击事件,复原按钮的开关变量来允许再次点击“开始闪"按钮,再清除定时器,并恢复原本颜色;
nineBoxs.btnEnd.onclick = function() {
this.className = "end-flicker btn-active";
nineBoxs.btnStart.className = "start-flicker btn-hover";
// 点击后按钮变色
nineBoxs.btnDisabled = false;
// 复原按钮的开关变量
clearInterval(nineBoxs.intervalId);
nineBoxs.boxRecover();
};
// 点击后取消间歇调用,并恢复原本颜色
三、 任务问题:
1. 按钮重复点击,会重复触发click事件,所以需要防止重复触发,由于此任务需要点击一次,所以可以绑定
disabled变量,通过修改其布尔值来是否允许再次点击生效,也可以点击后显示层叠比按钮高的控件(类似loading弹层),来使用户无法再次点触到按钮;
2. 而函数节流用于短时间内防止连续重复点击生效,减少连续多次对DOM节点的操作,即在指定的一段时间内多次点击,都会清除原来的定时器并设置一个新定时器(所定时间为剩余的时间),直到过了那段时间之后再点击,才再次生效,可用于等待验证码等延迟生效操作;
但是,看得明白函数如何运行,但使用时却没有预期的效果,还是没有弄明白函数节流
var throttle = function(func,delay){
var timer = null;
var startTime = Date.now();
return function(){
var curTime = Date.now();
var remaining = delay-(curTime-startTime);
var context = this;
var args = arguments;
clearTimeout(timer);
if(remaining<=0){
func.apply(context,args);
startTime = Date.now();
}else{
timer = setTimeout(func,remaining);
}
}
}
评论