1. 前言 ✨
在前端开发中,防抖(Debounce)和节流(Throttle)是两种常用的性能优化技术,用于处理频繁触发的事件(如表单提交、输入框输入、窗口 resize 等),避免因事件触发过于密集而导致的性能问题。下面我们用 console.log() 模拟一个表单提交场景:
当用户重复点击提交按钮时,数据会不断提交,这将显著增加服务器负担。如何解决这个问题呢?让我们一起进入今天的主题。
2. 防抖(Debounce)✨
2.1 概念 ⚡
防抖是指当事件被频繁触发时,不立即执行回调,而是等待事件停止触发后经过指定时间才执行一次。若在等待期间事件被再次触发,则重新计时。其核心思想是:在规定的等待时间内没有新触发,才执行回调。
2.2 原理 ⚙️
- 事件触发时设置延迟定时器
- 若在延迟期间再次触发,则清除旧定时器并重置延迟
- 延迟结束后执行回调
2.3 代码实现 💻
btn.addEventListener("click", debounce(submit, 2000));
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer); // 清除上次的定时器
timer = setTimeout(() => {
fn.call(this, ...args); // 延迟结束后执行
}, delay);
};
}
3. 节流(Throttle)✨
3.1 概念 ⚡
节流是指控制事件触发频率,确保回调函数在规定时间内只执行一次。其核心思想是:固定时间间隔内仅响应一次事件触发。
3.2 原理 ⚙️
- 事件触发时,若未进入冷却期则立即执行回调并进入冷却
- 冷却期内再次触发事件则被忽略
- 冷却期结束后可再次响应
3.3 代码实现 💻
方案1:定时器实现
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (!timer) { // 若无定时器则执行
timer = setTimeout(() => {
fn(...args);
timer = null; // 执行后释放定时器
}, delay);
}
};
}
方案2:时间戳实现
function throttle(fn, delay) {
let prevTime = 0; // 记录上次执行时间
return function (...args) {
const now = Date.now();
if (now - prevTime >= delay) { // 达到时间间隔
fn(...args);
prevTime = now; // 更新执行时间
}
};
}
4. 防抖和节流的区别 ✨
| 防抖(Debounce) | 节流(Throttle) | |
|---|---|---|
| 核心思想 | 响应事件停止触发后的最后一次操作 | 固定时间间隔内仅响应一次 |
| 效果 | 高频操作后只执行一次 | 有节奏地执行,按固定频率响应 |
| 使用场景 | 输入联想搜索、窗口 resize 事件、按钮防重复提交 | 游戏射击按钮、滚动加载、鼠标拖拽操作 |