00:00
哈喽,大家好。这个小题呢,我们来实现一下函数防抖的效果。函数防抖呢,它与函数截流呢一样,都是为了控制事件回调的执行频率。但是呢,它控制频率的方式呢,与节流是不太一样的。那他是怎么控制的?它是这样子的,就是当你的事件在触发之后。他不会立即执行回调。他会等待一段时间再去执行回调。那么在这个等待的时间过,等待这个时间当中,如果你再次触发了实践。那么他会再次等待上一个事件处理程序是不执行的。什么意思呢?我来给大家画个图,比方说你在这个位置触发的事件。假如就以上个案例的滚动事件来为例。你触发完事件之后呢,它不会立即执行回调。而是呢,等待一段时间,这个时间咱们现在假定是一秒钟。
01:00
一秒钟之后,你没有触发新的事件。没有触发新的滚动事件,它就会执行回调。但是如果说在这一秒钟当中,你又再一次的执行了,又再一次的触发的事件。比如说你又滚动了。那好,这个这个定时将重新开始。啊,再等一秒,如果说在这一秒当中你没有去。触发新的这个滚动事件。那么它就会执行回调,如果说呢,在这个新的一秒当中,你又再一次的。啊,在这个位置又产生了滚动。那么这个时候的话,他就会再次的重新开始计时。直到你啊,没有再次去触发,在这个时间间隔之内,你没有再次去触发事件的时候。他就会去执行回调。所以说,当你频繁的在触发某一个事件的时候。他不会执行啊,他只会执行最后那一个。
02:00
事件对应的回调。就是你最后那一次动作啊。时间的回调。啊,他是这样的一种思路。好了,那么下边的话,我们来实现一下啊,这个防抖的效果。那首先的话,我这儿呢,是写了一个小的页面,大家可以看一下。啊,这是一个音谱的元素。给他绑定了on key down,就是键盘按下事件。比如说我按an BN c nd。会在控制台输出当前按键对应的按键码。也就是ask吧。那好,那下面的话,我们就是想着。事件触发呢?用防抖的方式去控制。不要每一次我去按下,它都会去执行。呃,因为这样的话,如果涉及到服务器通信相关搜索。这样的话会给服务器造成很大压力。接下来我们来实现一下。首先还是一样。把结构先搭出来。
03:00
然后它这里边儿参数呢,跟。节流那块是一样的,第一个参数还是回调。第二个呢,是这个间隔,我们写一个time。然后呢,它的这个返回结果肯定也是个函数啊,为了能够看清这一点呢。我们这样来做一下。把上面这个注掉。然后呢,这块我们用。底半。调用一下,第一个参数是回调,第二个参数是间隔,我们来个一秒。你可以想象一下,它的这个返回值一定得是个函数。如果不是个函数的话,咱这事件在触发之后没法去执行回调。所以说返回值。啊,一个函数,这是必然的。Return function。然后呢,返回的函数呢,你这个地方还得加呀,加这个事件回调。啊,所以事件对象。
04:01
因为这玩意儿呢,呃,人家内部要用往里边传入参数的,如果你没有行参去接,到时候你在代码体里边没有办法获得时间对象。所以咱们把这个E呢给它补上。补上之后,那进来的话呢,我们就开始去启动一个定时器。啊,启动定时器。Set time out。啊,间隔这块咱们来一个time。啊,在这里边儿呢,我们去执行回调。回调怎么执行呢?啊,还是跟上面一样啊,跟这个截流是一样的,Call back.call。然后呢,里边this指向谁?就是这个回调啊,这个回调它在执行时this指向谁。他应该指向事件源。那么事件源又是谁呢?啊,其实事件源就是这个函数它的值。
05:00
而箭头函数有一个特点,就是它内部的this是指向外层作用下list的值的。所以说在这我们可以这样写,直接写个Z。啊,然后把参数往里边一传就搞定。那么这么写就完事了吗?其实这么写并没有完事。这么写一个有效果啊,不是说没有效果,但是这个效果呢,有点奇怪,我们一起来看一看。刷新页面。啊,他说is这是因为咱们没有引入文件导致的。Script s RC。然后boss。刷新一点。我。NB。按C。你会发现呢,它是每一次事件触发完毕之后,都会隔一秒钟在控制台输出这个结果。也就是说呢,他的事件呢。出发了,事件回调呢,也每次都执行了。那这样其实并没有达到我们的目的。
06:00
我们的目的是。就是在这个时间间隔当中,如果你再去处罚,比方说我AB。C我按的间隔一定是小于一秒的。那么在这种情况下,应该只有最后一次触发事件,然后呢执行事件回调。而不是说前边两次呢,他也执行啊,所以咱们这个效果并没有实现。那没有实现,咱们应该怎么办呢?哎,我们可以这样来做。我们维护一下它的一个返回结果。Time ID。我们先为这个time ID呢创建一个初始值啊,Let time ID等于none。当然,这个初始值你可以给任何值都行。啊,比如说你给一个这个,呃。负一。或者给一个unDeFined都可以。好,这是定时器的变量。然后呢,我们都知道啊,定时器一旦启动之后呢,它的set out set out,它的返回结果是一个数字。
07:01
是几呢?咱们目前咱先不知道是吧,他一般是从二开始的啊,然后咱们现在为止的话,咱们目前还不太清楚。但是他一定不是闹。那当我第二次再次去触发的时候呢,我们就可以做个判断。如果。这个time ID要是不等于呢。不等于,那表明什么呢?不等于,那就表明有一个定时器已经在跑了。所以这种情况下,我们就可以把定时器清空。让上一个定时器清空,让它时间回调,不要直线。咱们写clear timeout。把这个time ID给它清掉。这样一来,他就不会执行了。然后呢,我们再次去重新启动去执行回调。这样做是不是就完全搞定了?其实也并没有,这里有一个小瑕疵。
08:01
什么瑕疵呢?比方说我们在触发第一次事件之后,像这样子。我摁个A。他事件触发了对不对,那这个时候我再按B。我还在等。哎,他事件呢,也触发了。直行呢,是直行了,但是这里有个小的瑕疵。什么瑕疵呢?就是我们在执行了第一次回调之后。来看一下我na它执行了,我等一段等待等待一段一段时间,然后下边的话我再去按B。大家可以想一想啊,当我在按B的时刻。这个time ID的值是多少呢?等我第二次摁的时候,它其实不是闹。他是上一次time ID保留的那个数字。那既然是保留数字的话,这个代码它就会执行,然后去清空定时器,但是呢,它这个清空其实是无用的。你想象一下,咱们上一次那个直行那个电视器已经是结束了。
09:01
所以你执行这个代码没有任何的意义。虽然说效果出来了,但是呢,他并没有去,就是在,但但在这里的话,他这个逻辑并不是特别严谨。这里执行了一些无用代码。正确方式是当我们上一次在执行成功,执行回调之后,应该。要将这个定时器的变量呢,给它复原。所以说应该是要重置一下定时器变量。这样更为的合理一些。好,那么下边我们再来测试一下。刷新。然后ABCDEFG。好,你可以看一下,只有最后一次出发了。啊,然后前边这几次他都没有触发,通过这样一种方式就可以很好的控制。啊,这个事件它的触发频率。特别是这种相关关键字搜索的功能,它与服务器是直接挂钩的。
10:00
你这里输什么就会传递给服务器,如果你的触发频率不控制啊。它就会向服务器发送大量请求,给服务器造成压力。好了。这当前我们对。啊,防抖做了一个实线。
我来说两句