我们经常需要对操作次数进行限制,比如一次性的HTTP请求
具体的需求:用户勾选任务之后,任务会慢慢消失
做法:监听按钮的click事件,当发生点击时就改变样式(动画设置渐变消失),设置setTimeout 2s之后删除这个任务的节点。
问题:在节点还没删除的时候,如果多次点击,就有可能会报这个错误。
解决办法一:限制操作次数为1,在addEventListener中的最后一个option参数设置once为true,如下图所示。
let noneOnce = {
once : true
};
const list = document.querySelector('ul');
const buttons = list.querySelectorAll('input');
buttons.forEach((button) => {
// 我们为按钮绑定点击事件
button.addEventListener('click', (evt) => {
const target = evt.target;
// 改变当前点击的元素样式,渐变消失
target.parentNode.className = 'completed';
//console.log(target.parentNode) //li
// 两秒钟后删除这个元素
setTimeout(() => {
list.removeChild(target.parentNode);
}, 2000);
},noneOnce);
});
解决方法二:用高阶函数设计一个只能执行一次的函数
- 高阶函数:以函数作为参数 或者 以函数作为返回值 的函数
- 函数装饰器:同时满足以上两点,例如下面的once函数
function once(fn){
return function(){
if(fn){
//res:调用有指定this值和参数的函数的结果
const res = fn.apply(this,arguments)
fn = null
return res
}
}
}
const list = document.querySelector('ul');
const buttons = list.querySelectorAll('input');
buttons.forEach((button) => {
// 我们为按钮绑定点击事件,通过调用once就可以达到限制次数为1
button.addEventListener('click', once((evt) => {
const target = evt.target;
// 改变当前点击的元素样式,渐变消失
target.parentNode.className = 'completed';
//console.log(target.parentNode) //li
// 两秒钟后删除这个元素
setTimeout(() => {
list.removeChild(target.parentNode);
}, 2000);
}));
});