持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
一、什么是防抖
防抖:当用户触发某个事件的操作过于频繁,只执行最后一次对事件的操作。
其中包含几个要点:
- 持续触发事件
- 设置n秒的延时器,n秒内未触发,事件处理函数才会执行一次
- 如果在n秒内触发了,则重新计时
一般防抖会和节流进行对比记忆:
节流:当持续触发事件时,n秒内只调用一次事件处理函数,在这段时间内不会重新执行事件。
应用场景
防抖:
- 按钮(比如提交表单表单、登录、上传、点赞等操作)
- 远程模糊搜索(当用户停止输入后再调取接口数据,而非输入一个字母搜索一次)
- 浏览器窗口尺寸变化、scroll等
实现
-
我们可以认为防抖是闭包的实际应用
-
当浏览器尺寸发生变化,window.onresize不断的调整大小,使用防抖函数来避免发生不断重排与重绘的问题
-
实现:
原函数:
window.addEventListener('resize', ()=>{ console.log(document.documentElement.clientWidth) })
防抖后:
(Fn: 回调函数, delay:延迟执行的时间)
function debounce(Fn, delay){ var timer = null; return function(){ if(timer !== null){ clearTimeout(timer); } timer = setTimeout(Fn,delay); } } function getWidth(){ console.log(document.documentElement.clientWidth); // 屏幕尺寸 } window.addEventListener("resize",debounce(getWidth,1000));
实现步骤详解:
- 首先通过闭包缓存一个定时器timer,初始值设为null
- 将 debounce 处理结果作为函数返回
- 如果已经设定过定时器,清空上一次的定时器
- 设定一个新的定时器,重新开始计时,当定时器结束后执行传入的函数getWidth(),也就是我们进行防抖后最终要的那个函数
这种方式的缺点是:无法在第一次触发回调事件时就执行,需要等待定时器执行完毕之后才会执行事件
升级版防抖
在原版的基础上,改造debounce函数:增加了immediate参数,true表示立即执行。
当设为立即执行模式时,如果定时器为空,直接执行一次事件
function debounce(Fn, delay,immediate){
var timer = null;
return function(){
if(timer !== null){
clearTimeout(timer);
}
if(immediate && !timer) {
Fn.apply(this)
}
timer = setTimeout(Fn,delay);
}
}