防抖(debounce) & 节流(throttle)
防抖(debounce)
- 定义: 在规定的时间内如果事件被密集触发,则规定的时间重新计算并且规定的时间结束后只触发最后一次事件。
- 应用场景:
(1) 输入框中频繁的输入内容,搜索或者提交信息
(2) 频繁的点击按钮,触发某个时间
(3) 监听浏览器滚动事件,完成某些特定操作
(4) 用户缩放浏览器的resize事件
function debounce(fn, delay, immediate = false, resultCb) {
let timer = null
// 定义是否执行过
let isInvoke = false
// 不能用箭头函数,否则this指向声明的作用域
const _debounce = function(...args) {
if (immediate && !isInvoke) {
const res = fn.apply(this, args)
if (resultCb) {
resultCb(res)
}
isInvoke = true
} else {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
// 绑定触发对象的this和事件参数
const res = fn.apply(this, args)
if (resultCb) {
// 回调传递返回值
resultCb(res)
}
timer = null
// 设置为false下次事件第一次输入仍然是立即执行
isInvoke = false
}, delay)
}
}
// 取消功能 函数也是一个对象,可以挂载一个方法
_debounce.cancel = function() {
if (timer) clearTimeout(timer)
timer = null
isInvoke = false
}
return _debounce
}
节流(throttle)
- 定义: 在规定的一段时间内密集触发事件,事件只会触发一次,并且这段时间只有完全结束后才会重置( 一般都是执行规定时间内第一次触发的事件 )
- 应用场景:
(1) 监听页面的滚动事件
(2) 鼠标移动事件
(3) 用户频繁点击按钮操作
(4) 游戏中的一些设计( 飞机大战发射子弹 )
function throttle(fn, interval, options = {
leading: true,
trailing: false
}) {
// 上一次开始时间,默认为0
const {
leading = true,
trailing = false
} = options
let lastTime = 0
let timer = null
const _throttle = function(..args) {
// 每次触发时的当前时间
const nowTime = new Date().getTime()
// 如果是第一次进入并且不希望一开始就执行(leading === false)
if (lastTime === 0 && leading === false) {
lastTime = nowTime
}
// 计算剩余期间
const remainTime = interval - (nowTime - lastTime)
if (remainTime <= 0) {
// 如果有真正执行的函数,则不需要触发同一期间内非第一次执行的函数
if (timer) {
clearTimeout(timer)
timer = null
}
// 如果剩余期间小于等于0执行事件函数
fn.apply(this, args)
// 将本次当前时间设置为最后一次触发时间,进入下一个周期
lastTime = nowTime
return
}
// 范围期间内非第一次输入的值是否执行
if (trailing && !timer) {
// 只需要一个定时器
timer = setTimeout(() => {
timer = null
lastTime = !leading ? 0 : new Date().getTime()
fn.apply(this, args)
}, remainTime)
}
}
_throttle.cancel = function() {
if (timer) {
clearTimeout(timer)
timer = null
lastTime = 0
}
}
return _throttle
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!