侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论
Web

debounce & throttle

barwe
2022-03-26 / 0 评论 / 0 点赞 / 1,300 阅读 / 1,716 字
温馨提示:
本文最后更新于 2022-04-03,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

debounce 翻译为 "防抖",throttle 翻译为 "节流"。

传统模式下,事件的触发和事件的处理是一一绑定的,即每次触发都会被处理。

这在某些情况下会无意义的多次调用处理函数,例如缩放元素的大小。

我们只关心拖动事件结束之后元素的大小,而不关心拖动过程中触发的一系列事件。

再例如滚动事件,我们的一次滚动可能会触发大量的滚动事件,然而我们往往只关心滚动结束之后的结果。


Debounce

将间隔事件较短的多次触发事件合并为一个事件处理,即只调用一次处理函数。

你可以在这组事件第一次触发时执行函数,忽略之后的事件;也可以在最后一次事件触发后的一定延迟后执行函数。

lodash.debounce 函数提供了 Debounce 功能,它有两个标志位:leading & trailing

leading 在事件组第一个开始时执行函数,trailing 在事件组最后一个事件发生后的一段时间执行函数。

为什么 trailing 需要等待一段时间?因为就是靠这段时间来划分事件组的范围。

debounce<T extends (...args: any) => any>(func: T, wait?: number, options?: DebounceSettings): DebouncedFunc<T>;
interface DebounceSettings {
    leading?: boolean | undefined; // 调用函数后等待
    maxWait?: number | undefined; // func 允许被延迟的最大值
    trailing?: boolean | undefined; // 等待后调用
};
interface DebouncedFunc<T extends (...args: any) => any> {
    (...args: Parameters<T>): ReturnType<T> | undefined;
    cancel(): void; // 取消防抖函数的调用
    flush(): ReturnType<T> | undefined; // 立即调用
}

wait 用来设置事件发生多少毫秒后调用函数,如果下一次事件触发时间少于这个值,两次事件会被划分为同一个事件组。

wait 也是 func 函数延迟执行的默认值。

options.maxWaitwait 的关系还没搞懂。

抖动函数会返回一个抖动对象,可以取消抖动函数的调用 (cancel),或者立即调用函数一次 (flush)。


Throttle

lodash.throttle 提供了节流功能,在连续触发的事件(例如滚动)中,在指定毫秒内最多执行一次函数。

_.throttle(func, [wait=0], [options=])

options 有两个选项:

  • leading boolean 在节流开始时调用函数
  • trailinf boolean 在节流结束时调用函数

“节流” 就是将连续事件持续的这段时间等分成一定份数,在每段时间里面只执行一次函数。

可以在这段时间开始执行,也可以在结束时执行。


rAF

window.requestAnimationFrame 方法。

功能相当于 lodash.throttle(func, 16),即 1 帧(16ms,60fps)内的节流。

但是更加可靠和稳定,因为是浏览器提供的原生 API。

还有一个类似的 API 是 setInterval,尽量用 requestAnimationFrame 代替。

当执行函数涉及到绘制 DOM 时建议使用 requestAnimationFrame

requestAnimationFrame 会把所有帧中对 DOM 的操作收集起来,在一次重绘中完成所有操作,并且重绘的时间间隔与浏览器的刷新频率保持一致。

在隐藏元素或者不可见元素中,requestAnimationFrame 不会进行重绘或者回流,减少系统资源占用。


Reference

0

评论区