Js函数节流

一、开始

很多时候一些事件我们希望他一段时间内只被触发一次,比如轮播图之类的,多次点击就会被处理为一次。

这个问题被称作“防抖(节流)”问题,可以通过设置定时器来解决

二、模拟

我们模拟一个会被多次触发的事件,这里选用 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 内的数字来看这个事件的触发情况:
0.gif

可以看到从左到右移动鼠标触发了这个时间 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;
}

1.gif

现在变成了鼠标移动停止后一秒再执行处理函数。

正常情况下我们不可能直接拿到要操作的 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;
}

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