节流
函数执行一次后,只有在大于设置的执行周期后才会执行第二次。持续触发事件时,保证一定时间段内只调用一次事件处理函数
- 规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效
- 好比玩游戏时法师释放的技能,它有冷却时间,在一定时间内,只能释放一次技能
原理
原理是通过判断是否到达规定时间来触发函数。
运用场景
- 鼠标不断点击触发,mousedown 事件的执行(单位时间内只触发一次)
- 监听滚动事件,比如是否滑到底部自动加载更多,用节流来判断
代码实现
用一个可拖拽的div模拟:
结果:
导致移动一点点都会触发事件,打印了好多😭,设想如果里面设计dom查询之类的,那么性能定会堪忧,so,节流来帮忙!
const div1 = document.getElementById('div1')
let timer = null
div1.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 = null
return 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 = null
input1.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 = null
return 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))
结果:
欢迎打家纠错😂
参考文章