JS节流防抖函数
JS节流防抖函数我们在很多场景都会用到,例如:在进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验特别差。这里我们就可以采用debounce(防抖)和throttle(节流)的方式来减少函数调用频率,从而提升用户体验。
html中的代码
在上述代码中,div 元素绑定了 mousemove 事件,当鼠标在 div(灰色)区域中移动的时候会持续地去触发该事件导致频繁执行函数。效果如下
可以明显地看到,在没有通过其它操作的情况下,函数被频繁地执行导致页面上数据变化特别快。所以,接下来让我们来看看防抖和节流是如何去解决这个问题的。
防抖函数
防抖函数(debounce):当持续多次触发事件时,约定一定时间段内如果没有再次触发事件,那么事件处理函数才会执行一次,如果在设定时间到来之前,用户又一次触发了事件,那么就重新开始计时。如下图,当持续触发scroll事件时,并不马上执行handle函数,当1000毫秒内没有再次触发scroll事件时,才会延时触发scroll事件。
我们可以来实现一个简单防抖
|
|
这里防抖还可以分为两种:‘立即执行防抖函数’和‘非立即执行防抖函数’
1、立即执行防抖函数
立即执行的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
效果如下
2、非立即执行防抖函数
非立即执行的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
|
|
先看看效果
可以看到,在触发事件后函数 1 秒后才执行,而如果我在触发事件后的 1 秒内又触发了事件,则会重新计算函数执行时间。
上述防抖函数的代码还需要注意的是 this 和 参数的传递
防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
在实际开发过程中,我们需要根据不同的场景来决定我们需要使用哪一个版本的防抖函数,一般来讲上述的防抖函数都能满足大部分的场景需求。但我们也可以将非立即执行版和立即执行版的防抖函数结合起来,实现最终的双剑合璧版的防抖函数。
|
|
节流函数
节流函数(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。如下图,持续触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次handle函数。
函数节流主要有两种实现方法:时间戳和定时器。
节流throttle代码(时间戳):
效果是这样的
可以看到,在持续触发事件的过程中,函数会立即执行,并且每 1s 执行一次。
节流throttle代码(定时器):
|
|
使用方式同上,效果如下
可以看到,在持续触发事件的过程中,函数不会立即执行,并且每 1s 执行一次,在停止触发事件后,函数还会再执行一次。
我们应该可以很容易的发现,其实时间戳版和定时器版的节流函数的区别就是,时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
同样地,我们也可以将时间戳版和定时器版的节流函数结合起来,得到最终版节流函数。