一、开始
很多时候一些事件我们希望他一段时间内只被触发一次,比如轮播图之类的,多次点击就会被处理为一次。
这个问题被称作“防抖(节流)”问题,可以通过设置定时器来解决
二、模拟
我们模拟一个会被多次触发的事件,这里选用 mousemove,每移动一次鼠标就会触发:
1 2 3 4 5 6 7 8
| var wra = document.getElementById('wrapper'); var inn = 0; wra.innerText = inn; wra.onmousemove = over;
function over(e){ wra.innerText = ++inn; }
|
我们通过改变 wrapper 内的数字来看这个事件的触发情况:

可以看到从左到右移动鼠标触发了这个时间 78 次。
现在我们通过改变代码实现在一秒内只触发一次:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var wra = document.getElementById('wrapper'); var inn = 0; wra.innerText = inn; wra.onmousemove = over();
function over(e){ var timer; return function(){ clearTimeout(timer); timer = setTimeout(function(){ deal(); },1000) } }
function deal(){ wra.innerText = ++inn; }
|

现在变成了鼠标移动停止后一秒再执行处理函数。
正常情况下我们不可能直接拿到要操作的 dom 元素,需要再执行函数拿到,如果我们直接再 deal 里面打印 this,得到的会是 window,而不是我们要的 dom,
所以我们要把触发事件的 dom 元素保存起来,传给 deal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var wra = document.getElementById('wrapper'); var inn = 0; wra.innerText = inn; wra.onmousemove = over();
function over(e){ var timer; return function(){ var _this = this; clearTimeout(timer); timer = setTimeout(function(){ deal.apply(_this); },1000) } }
function deal(){ this.style.background = 'white'; this.style.color = 'black'; this.innerText = ++inn; }
|

我们把触发事件的 this 传给 deal,并改变了 this 的背景和文字颜色,当然也可以传参,加在 apply()