在前端开发中,防抖(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. 总结
-
防抖 是一种优化技术,用于限制函数在短时间内被频繁调用的次数。
-
它的核心思想是:在一定时间内,无论触发多少次事件,只执行最后一次操作。
-
防抖常用于处理用户输入、窗口调整、滚动事件等高频触发的场景。
-
通过防抖,可以减少不必要的计算或请求,提升性能。