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.maxWait
与 wait
的关系还没搞懂。
抖动函数会返回一个抖动对象,可以取消抖动函数的调用 (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
不会进行重绘或者回流,减少系统资源占用。
评论区