你有没有遇到过这种情况:点击"提交订单"按钮,因为网络卡了点了两下,结果生成了两个订单?或者搜索框输入时,每输一个字就发一次请求,服务器直接"累到罢工"?这时候,JS防抖(Debounce)就能派上大用场了!
什么是防抖?
简单来说,防抖就是让函数"冷静"一下再执行。如果在短时间内频繁触发同一个函数,防抖会忽略前面的触发,只执行最后一次。就像你在电梯里按关门键,只要有人不断按,电梯就会一直等,直到没人按了才关门。
为什么需要防抖?
- 减少请求次数:搜索框输入时,防抖可以等用户输入完成后再发请求,而不是每输一个字就发一次,大大减轻服务器压力。
- 避免重复操作:按钮点击时,防抖可以防止用户快速连点导致的重复提交(比如下单、支付)。
- 提升性能:对于一些复杂的DOM操作(比如窗口
resize时计算元素位置),防抖可以避免频繁计算,让页面更流畅。
防抖函数怎么写?(超简单版)
下面是一个基础版的防抖函数,代码不多,注释也写得很清楚:
javascript
// 防抖函数:func是要执行的函数,delay是延迟时间(毫秒)
function debounce(func, delay) {
let timer = null; // 定时器ID
// 返回一个新函数
return function(...args) {
// 如果定时器存在,清除它(取消上一次的延迟执行)
if (timer) clearTimeout(timer);
// 重新设置定时器,delay毫秒后执行func
timer = setTimeout(() => {
func.apply(this, args); // 执行原函数,并传递参数
}, delay);
};
}
实际例子:按钮防抖
假设我们有一个"提交订单"按钮,点击后会调用 submitOrder() 函数。如果用户快速点击多次,就会重复提交。我们用防抖来解决这个问题:
html
<button id="submitBtn">提交订单</button>
<script>
// 模拟提交订单的函数
function submitOrder() {
console.log("订单提交成功!");
// 这里可以写真实的接口请求代码
}
// 使用防抖包装submitOrder,延迟500毫秒执行
const debouncedSubmit = debounce(submitOrder, 500);
// 给按钮绑定点击事件,触发防抖后的函数
document.getElementById("submitBtn").addEventListener("click", debouncedSubmit);
</script>
现在,即使你在500毫秒内点击10次按钮,也只会执行一次 submitOrder() ,完美解决了重复提交的问题!
实际例子:搜索框防抖
再来看一个搜索框的例子。用户输入时,我们希望等用户停止输入1秒后,再发送搜索请求:
html
<input type="text" id="searchInput" placeholder="请输入关键词搜索">
<script>
// 模拟搜索接口请求
function search(keyword) {
console.log(`正在搜索:${keyword}`);
// 这里可以写真实的搜索接口请求代码
}
// 使用防抖包装search,延迟1000毫秒执行
const debouncedSearch = debounce(search, 1000);
// 给搜索框绑定输入事件
document.getElementById("searchInput").addEventListener("input", function(e) {
debouncedSearch(e.target.value); // 传递输入框的值给搜索函数
});
</script>
现在,用户输入"手机"时,不会每输一个字就搜索一次,而是等用户停止输入1秒后,才会执行一次搜索,大大减少了请求次数。
防抖的小细节
- 延迟时间的选择:延迟时间
(delay)要根据实际场景调整。按钮防抖一般用300-500毫秒,搜索框防抖一般用500-1000毫秒。 - 立即执行:有时候我们希望第一次触发时立即执行,之后才防抖(比如按钮点击后立即禁用,防止重复点击)。这种情况可以给防抖函数加一个
immediate参数,稍微修改一下代码即可实现(进阶需求,基础版暂时用不到)。
总结
记住这个简单的防抖函数,下次遇到"手抖"问题时,直接拿来用就可以啦!需要我帮你写一个带"立即执行"功能的进阶版防抖函数吗?