-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
防抖和节流 #21
Comments
防抖和节流都是为了降低某个事件的触发频率,减少无用的触发次数。 debounce 防抖触发一个事件,等待n秒后执行,如果n秒内又触发了这个时间,以新的事件为准,n秒后执行,直到触发事件n秒内不再触发,才执行。 举个栗子:一部直梯,陆续往上上人(连续触发),当不再上人的时候(停止连续触发),电梯才会关门并动起来(执行方法)。 再举个栗子: 代码实现: const debounce = (fn, ms = 0) => {
let timeout
return function (...args) {
clearTimeout(timeout)
timeout = setTimeout(() => fn.apply(this, args), ms)
}
} 立即执行如果希望触发后可以立即执行,等停止触发n秒后,才可以重新触发执行。 const debounce = (fn, ms, immediate) => {
let timeout
return function (...args) {
if (timeout) clearTimeout(timeout)
// timeout为空表示第一次触发
if (immediate && !timeout) {
fn.apply(this, args)
}
timeout = setTimeout(() => {
fn.apply(this, args)
}, ms)
} 取消增加一个取消功能,取消防抖后可以跳过等待间隔立即执行。 const debounce = (fn, ms, immediate) => {
let timeout
const debounced = (...args) => {
clearTimeout(timeout)
if (immediate) {
let callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, ms)
if (callNow) fn.apply(this, args)
}else {
timeout = setTimeout(() => fn.apply(this, args), ms)
}
}
debounced.cancel = () => {
clearTimeout(timeout)
timeout = null
}
return debounced
} DEMO:See the Pen debounce-demo by kk (@kk124) on CodePen. |
Throttle ['θrɑtl] 节流持续触发事件,每隔一段事件只执行一次。 举个栗子:当鼠标移入的时候,事件立刻执行,每过 1s 会执行一次,如果在 4.2s 停止触发,以后不会再执行事件。 节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。 使用时间戳代码实现: const throttle = (fn, wait) => {
let previous = 0
return function (...args) {
let now = Date.now()
if (now - previous > wait) {
fn.apply(this, args)
previous = now
}
}
} 使用定时器代码实现: const throttle1 = (fn, ms) => {
let timeout
return function (...args) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null
fn.apply(this, args)
}, ms)
}
}
} 当然, const throttle2 = (fn, ms) => {
let timeout
return function (...args) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null
}, ms)
fn.apply(this, args)
}
}
} 上图显示了两者的区别,那么接下来实现一个开始立即执行,且停止触发间隔时间后也执行的节流。 const throttle = (fn, wait) => {
let inThrottle, lastFn, lastTime
return function (...args) {
if (!inThrottle) {
fn.apply(this, args)
lastTime = Date.now()
inThrottle = true
} else {
clearTimeout(lastFn)
lastFn = setTimeout(() => {
if (Date.now() - lastTime >= wait) {
fn.apply(this, args)
lastTime = Date.now()
}
}, Math.max(wait - (Date.now - lastTime), 0))
}
}
} |
参考:
https://juejin.im/post/5cce5380f265da03826129bf
mqyqingfeng/Blog#22
mqyqingfeng/Blog#26
The text was updated successfully, but these errors were encountered: