防抖与节流:优化事件处理的性能
在开发过程中,我们经常会遇到需要优化事件处理性能的场景。本文将介绍两种常用的技术:防抖(debounce)和节流(throttle),并提供实现思路和代码示例。
防抖(Debounce)
概念
事件连续触发,防抖函数在设定时间内没有被触发过才会执行事件函数,在设定时间内如果被触发过,就会重新计时,从而防止事件被频繁触发;
应用场景
- 搜索框输入:在用户完成输入后,才发送搜索请求。
- 窗口调整:在用户停止调整窗口大小时,再计算布局。
- 点击按钮:当用户点击某些按钮时,会调用接口,防止用户连续点击后多次发送请求。
实现思路
- 定义一个防抖函数,接收事件函数和等待时间作为参数。
- 使用一个变量来存储定时器,用来控制事件函数是否执行。
- 返回一个回调函数,在事件触发时调用,清除旧的定时器并返回一个新的定时器,在定时器内使用 apply 方法调用事件函数,并保存this指向。
js
// 防抖函数实现
function debounce(func, wait) {
let timeout = null;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
// 使用示例
const inputDom = document.getElementById('debounceInput');
inputDom.oninput = debounce((e) => {
console.log('查询参数', e.target.value);
}, 500);
节流(Throttle)
概念
事件连续触发,节流技术控制事件函数,在设定的时间内只执行一次,降低事件触发的频次;
应用场景
- 滚动加载:在用户滚动页面时,控制加载更多内容的频率。
- 鼠标跟踪:跟踪鼠标移动的位置,但限制事件触发的频率。
实现思路
- 使用一个变量来存储定时器,控制事件函数是否可以执行的标识。
- 返回一个回调函数,在事件触发时调用,判断变量是否是“忙碌”状态。
- 如果状态为“不忙碌”,执行事件函数并设置定时器。
- 如果状态为“忙碌”,就不执行事件函数,等待定时器重置变量。
js
// 节流函数实现
function throttle(func, wait) {
let timer = null;
return function(...args) {
if (!timer) {
func.apply(this, args);
timer = setTimeout(() => {
timer = null;
}, wait);
}
};
}
// 使用示例
window.addEventListener('scroll', throttle((e) => {
console.log('节流参数', window.scrollY);
}, 500));
结论
通过使用防抖和节流技术,我们可以有效地控制事件处理的频率,从而提高应用的性能和用户体验。这两种技术各有适用场景,选择合适的技术可以解决特定的性能问题。