在前端开发中,防抖(Debounce) 是一种优化技术,用于限制某个函数在短时间内被频繁调用的次数。它的核心思想是:在一定时间内,无论触发多少次事件,只执行最后一次操作。防抖通常用于处理用户输入、窗口调整、滚动事件等高频触发的场景,以减少不必要的计算或请求,提升性能。
1. 防抖的应用场景
常见场景
搜索框输入:
当用户在搜索框中输入内容时,每次按键都会触发搜索请求。如果不做防抖处理,可能会导致大量不必要的请求。
使用防抖后,只有在用户停止输入一段时间后,才会触发搜索请求。
窗口调整(resize):
当用户调整浏览器窗口大小时,会频繁触发
resize
事件。使用防抖后,只有在用户停止调整窗口大小一段时间后,才会执行相关逻辑。
滚动事件(scroll):
当用户滚动页面时,会频繁触发
scroll
事件。使用防抖后,只有在用户停止滚动一段时间后,才会执行相关逻辑。
按钮点击:
当用户快速点击按钮时,可能会触发多次点击事件。
使用防抖后,只有在用户停止点击一段时间后,才会执行点击逻辑。
2. 防抖的实现原理
防抖的核心原理是:
设置一个定时器,在事件触发后等待一段时间。
如果在这段时间内再次触发事件,则清除之前的定时器,重新开始计时。
只有当事件停止触发一段时间后,才会执行目标操作。
3. 防抖的实现代码
原生 JavaScript 实现
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout); // 清除之前的定时器
timeout = setTimeout(() => {
func.apply(this, args); // 在延迟后执行目标函数
}, delay);
};
}
使用示例
function onInput() {
console.log('Input value:', document.getElementById('search').value);
}
const debouncedInput = debounce(onInput, 300);
document.getElementById('search').addEventListener('input', debouncedInput);
解释:
debounce
函数返回一个新的函数,这个新函数会在事件停止触发delay
毫秒后执行目标函数func
。每次事件触发时,都会清除之前的定时器并重新开始计时。
Vue 3 中使用 customRef
实现防抖
import { customRef } from 'vue';
function useDebouncedRef(value, delay = 300) {
let timeout;
return customRef((track, trigger) => {
return {
get() {
track(); // 追踪依赖
return value;
},
set(newValue) {
clearTimeout(timeout); // 清除之前的定时器
timeout = setTimeout(() => {
value = newValue; // 更新值
trigger(); // 触发更新
}, delay);
},
};
});
}
// 在组件中使用
export default {
setup() {
const debouncedValue = useDebouncedRef('');
return {
debouncedValue,
};
},
};
解释:
useDebouncedRef
是一个自定义的防抖ref
。在
set
方法中,使用setTimeout
延迟更新值,从而实现防抖效果。
4. 防抖与节流的区别
特性 | 防抖(Debounce) | 节流(Throttle) |
---|---|---|
定义 | 在事件停止触发一段时间后执行一次操作 | 在一定时间间隔内只执行一次操作 |
适用场景 | 输入框搜索、窗口调整、滚动事件等 | 滚动事件、鼠标移动、按钮点击等 |
核心逻辑 | 每次触发事件时重置定时器 | 在一定时间间隔内只执行一次操作 |
执行时机 | 事件停止触发后执行 | 按照固定时间间隔执行 |
5. 防抖的实际应用示例
示例 1:搜索框防抖
<input type="text" id="search" placeholder="Search..." />
<script>
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
function search() {
const query = document.getElementById('search').value;
console.log('Searching for:', query);
// 这里可以发起搜索请求
}
const debouncedSearch = debounce(search, 300);
document.getElementById('search').addEventListener('input', debouncedSearch);
</script>
解释:
用户在搜索框中输入内容时,只有在停止输入 300 毫秒后,才会触发搜索逻辑。
示例 2:窗口调整防抖
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
function onResize() {
console.log('Window resized:', window.innerWidth, window.innerHeight);
}
const debouncedResize = debounce(onResize, 200);
window.addEventListener('resize', debouncedResize);
解释:
当用户调整窗口大小时,只有在停止调整 200 毫秒后,才会触发
onResize
逻辑。
6. 总结
防抖 是一种优化技术,用于限制函数在短时间内被频繁调用的次数。
它的核心思想是:在一定时间内,无论触发多少次事件,只执行最后一次操作。
防抖常用于处理用户输入、窗口调整、滚动事件等高频触发的场景。
通过防抖,可以减少不必要的计算或请求,提升性能。