防抖与节流,其实是控制事件触发频率的方法。
在网页的实际运行的某些场景下,有些事件会持续被触发,比如resize不是我们需要的滚动一次,触发一次;由于频繁的DOM操作与资源加载,严重影响了网页性能,甚至会造成浏览器崩溃。
应用场景主要有:输入框持续输入,输入内容远程校验,多次触发点击事件,onScroll等。
一.防抖
抖动,即执行。一般的抖动都是持续,多次的。如果函数持续多次执行,或许不是想要的效果。我们更希望让它冷静下再执行。即当持续触发事件的时候,函数时完全不执行的,等到最后触发结束后的一段时间再执行。
比如:在输入框进行输入操作时,每次输入之后都有联想词弹出,这个控制联想词的方法就需要是结束输入后一段时间才触发。
应用场景:
实时搜索,拖拽,登录信息格式验证等。
此时需求:
(1)持续触发不执行;
(2)不触发则隔段时间后执行
可以很快想到利用setTimeout,调用要执行的函数,传入arguments
首先封装一个函数,让持续触发的事件监听是封装的这个函数,将目标函数作为回调函数传进来,等待一段时间过后执行目标函数(fun)
代码如下:
其次,第一个需求还没有实现,要如何持续触发 不执行?此时持续触发时不能有setTimeout,所以在事件持续触发时清除定时器即可。
代码如图所示,当事件持续触发时,清除定时器,setTimeout就不会执行了。
二.节流
节流,即让函数有节制地执行,而非毫无节制触发一次执行一次。
而有节制地执行,就是在一段时间内,只执行一次。
即:一个函数只有在超过执行周期时才执行,周期内调用不执行。
应用场景:
窗口调整,页面滚动,抢购操作等。
在购物网站抢购,总会不断点击鼠标,这时有一段时间点击鼠标是不起作用的,即不会产生效果,这里就是运用了节流,防止点击太快产生bug。
分析此时的需求:
(1)持续触发不会执行多次
(2)到一定时间再执行
这里划重点:执行的时间
所以要想控制执行的时间,可以通过一个开关,结合setTimeout。
持续触发不执行时,开关状态为关闭;
到一定时间,开关 打开,函数执行。
代码实现如下:
如果开关是关闭的,直接不执行。
或者可以通过使用时间间隔来控制,记录上一次函数的执行时间(prev),与当前时间(now)作比较,如果时间差大于特定值(wait),就执行。
代码实现如下:
总结
二者区别:发生持续触发事件时,防抖设置事件延迟并在空闲时间触发事件;节流则是隔一段时间触发一次。
相同点:防抖与节流都使用了setTimeout,以此来控制函数执行的时间。
优点:提高性能,不会出现多次触发而导致页面卡顿的情况。