一. 理解防抖(Debounce)和节流(Throttle)
防抖(Debounce)
防抖是指在一定时间内,如果事件被连续触发,则只执行最后一次触发的事件处理函数。如果在设定的时间间隔内事件又被触发,则重新计时。
比喻:就像电梯门,当有人进出时会一直保持开门状态,直到最后一个人进入后等待一段时间才关门。
节流(Throttle)
节流是指在一定时间内,无论事件被触发多少次,都只执行一次事件处理函数。
比喻:就像水龙头,无论你拧得多快,水流的速度都是固定的。
二. 手写实现
防抖实现
function debounce(fn, t) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, t);
};
}
节流实现
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
// 使用定时器实现的版本
function throttle(fn, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
}
三. 主要应用场景
防抖的应用场景
-
搜索框输入联想(等待用户停止输入后再发送请求)
-
窗口大小调整(等待调整结束后再计算布局)
-
表单验证(用户输入完再进行验证)
-
防止按钮重复点击
节流的应用场景
-
滚动加载更多(滚动过程中定期检查位置)
-
鼠标移动事件(如拖拽元素)
-
游戏中的按键操作(限制操作频率)
-
高频点击提交(如抢购按钮)
四. 各框架和库中的实现
Vue中的使用
Vue本身没有内置防抖/节流,但可以轻松实现:
// 在methods中
methods: {
search: debounce(function(query) {
// 搜索逻辑
}, 500)
}
React中的使用
React同样没有内置,但可以使用hooks实现:
import { useCallback } from 'react';
function SearchComponent() {
const debouncedSearch = useCallback(
debounce(query => {
// 搜索逻辑
}, 500),
[]
);
return <input onChange={e => debouncedSearch(e.target.value)} />;
}
Lodash中的实现
Lodash提供了现成的_.debounce
和_.throttle
:
import _ from 'lodash';
// 防抖
const debouncedFn = _.debounce(fn, 300);
// 节流
const throttledFn = _.throttle(fn, 300);
现代浏览器API
较新的浏览器提供了requestIdleCallback
和requestAnimationFrame
,也可以用于实现类似节流的效果:
function throttleWithRAF(fn) {
let ticking = false;
return function(...args) {
if (!ticking) {
requestAnimationFrame(() => {
fn.apply(this, args);
ticking = false;
});
ticking = true;
}
};
}