一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
什么是防抖:
防抖一词来源于电子产品,在我们按下一个按钮,比如按下电视遥控器,信号会快速的传输到遥控器的微芯片。在手指没有抬起时,信号会弹跳。微芯片会记录多次点击。
为了缓解这种情况,一旦接收到来自按钮的信号,微芯片就会在一定时间内停止处理来自按钮的信号,虽然我们不会超快速连续点击按钮。
JavaScript中的防抖:
在JavaScript中,原理是非常相似的。当我们触发一个函数时,每个用例只出发一次。假设有一个搜索框,我们需要显示搜索关键词建议,在用户完成输入之后。或者是一些输入框的校验,需要在用户输入完成时触发,而不是即时触发。
接下来一起看看debounce函数的简单实现。
function debounce(func, timeout = 300){
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}
function saveInput(){
console.log('Saving data');
}
const processChange = debounce(() => saveInput());
假设当前有一个输入框,调用了上面的debounce函数。当用户使用键盘输入时,输入完第一个字母后,debounce函数重置了计时器,clearTimeOut(timer),在300ms内,会调用saveInput()函数。假如用户一直在输入,每次按钮释放就会触发debounce一次,每次调用都会重置计时器。只要用户一起输入,每300ms就会调用一次saveInput()。
当用户输入完成,最后的计时结束后,执行saveInput函数。
这个debounce函数做了两个特殊任务:
- 为计时器变量分类了时间范围。
- 安排可以在特定的时间出发。
对于上述提到的遥控器防抖,在代码中有相似的用法,比如:当用户点击提交按钮,或注册按钮时,短时间内我们只需要用户的一次提交。
function debounce_leading(func, timeout = 300){
let timer;
return (...args) => {
if (!timer) {
func.apply(this, args);
}
clearTimeout(timer);
timer = setTimeout(() => {
timer = undefined;
}, timeout);
};
}
在上面的函数中,第一次单击按钮时,将会触发一次saveInput()函数。300ms内的多次点击,都不会触发saveInput()函数。
在工作项目中,我们无需自己实现debounce函数,有很多JavaScript库中都有实现。我之前项目中用的这个:Lodash Documentation。