
节流
函数执行一次后,只有在大于设置的执行周期后才会执行第二次。持续触发事件时,保证一定时间段内只调用一次事件处理函数
- 规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效
- 好比玩游戏时法师释放的技能,它有冷却时间,在一定时间内,只能释放一次技能
原理
原理是通过判断是否到达规定时间来触发函数。
运用场景
- 鼠标不断点击触发,mousedown 事件的执行(单位时间内只触发一次)
- 监听滚动事件,比如是否滑到底部自动加载更多,用节流来判断
代码实现
用一个可拖拽的div模拟:


结果:

导致移动一点点都会触发事件,打印了好多😭,设想如果里面设计dom查询之类的,那么性能定会堪忧,so,节流来帮忙!
const div1 = document.getElementById('div1')let timer = nulldiv1.addEventListener('drag', function (e) {if (timer) {return}timer = setTimeout(() => {console.log(e.offsetX, e.offsetY)timer = null}, 100)})
结果为每隔100毫秒打印一次😄,为了方便封装一哈:
const div1 = document.getElementById('div1')function throttle(fn, delay = 100) {let timer = nullreturn function () {if (timer) {return}timer = setTimeout(() => {fn.apply(this, arguments)timer = null}, delay)}}div1.addEventListener('drag', throttle(function (e) {console.log(e.offsetX, e.offsetY)}))
防抖
维护一个计时器,在规定的delay时间后触发函数,在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
- 当持续触发事件时,一定时间段内没有再次触发事件,事件处理函数才会执行一次,如果在设定的时间到来之前,又一次触发了事件,就重新开始延时
- 好比玩游戏时英雄回泉水,当点击了回泉水时,就不能中断,如果中断就得重新来过
原理
其原理是维护一个计时器,规定在 delay 时间后触发函数,但是在 delay 时间内再次触发的话,就会取消之前的计时器而重新设置;这样一来,只有最后一次操作能被触发。
运用场景
- input 输入框实现模糊匹配功能,用户在不断输入值时,用防抖来节约请求资源
- window 触发 resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
代码实现
input 输入框未做处理时


结果:

显而易见,每次输入都会触发,这很不理想,那么用防抖优化一哈,让它等个500毫秒:
const input1 = document.getElementById('input1')let timer = nullinput1.addEventListener('keyup', function () {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {// 模拟触发 change 事件console.log(input1.value)// 清空定时器timer = null}, 500)})
结果:

为了方便起见,我们简单封装一下:
// 防抖function debounce(fn, delay = 500) {// timer 是闭包中的,避免外部修改let timer = nullreturn function () {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {fn.apply(this, arguments)timer = null}, delay)}}input1.addEventListener('keyup', debounce(function (e) {console.log(e.target)console.log(input1.value)}, 600))
结果:

欢迎打家纠错😂
参考文章
