JavaScript系列 -- 防抖、节流

284 阅读2分钟

防抖

很多项目有这样一个需求:监听输入框输入的内容

<input type = "text" id = "input" />
<script>
window.onload = function(){
    var input = document.getElementById("input");
    input.addEventListener('input', function(e) {
        console.log(e.target.value);
    });n
}
</script>

效果:

很明显可以看到在极短时间内重复输入都会触发监听事件,这虽然每次都可以获得最新的输入内容,但这性能上就显得比较差一些,所以我们可以采用【防抖】来做性能优化:

<input type = "text" id = "input" />
<script type="text/javascript">
window.onload = function() {
    var input = document.getElementById("input")
    let timer = null; // 定义一个全局的定时器对象变量
    input.addEventListener('input', function (e) { // 监听其input事件
	clearTimeout(timer); // 清除上一个定时器
	timer = setTimeout(function () {
            console.log(e.target.value); // 代表 AJAX 请求
	}, 500);
    });
}
</script>

防抖的思路是:短时间 t 内的多次操作,会舍弃掉前面的上一次的操作,等到时间 t 一过才将此次操作弹出

所以防抖的关键步骤就是:

  1. 规定时间内的每次操作,都会各自清除之前的工作记录(即定时器)clearTimeout(timer)
  2. 规定时间一过,没有被干扰到的那个操作顺利完成工作(定时器计时完成,做出一些处理)timer = setTimeout(fn,delay)

效果:

节流

假如有这么一个需求:右边滚动条在滑动时,如果超过一定的范围,则左边的分类栏要同步更新显示当前所处的范围对应的类别:

image.png

那我们很容易想到的思路就是

  1. 监听滑动事件,实时获取到滚动条当前所处位置到顶部的距离
  2. 根据这个距离判断属于哪个范围,然后对数据做出修改

所以关键步骤在于:监听滑动事件,实时获取到滚动条当前所处位置到顶部的距离

function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
window.onscroll  = showTop

效果:

节流前.gif

可以看到,我们在极短时间内超多次获取滚动条位置,所以这个时候我们需要做一下节流优化:

// 节流函数
function throttle(fn,delay){
    let flag = true
    return function() {
       if(!flag){
           //休息时间 暂不接客
           return false 
       }
       // 工作时间,执行函数并且在间隔期内把状态位设为无效
        flag = false
        setTimeout(() => {
            fn()
            flag = true;
        }, delay)
    }
}
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop,1000)

节流的思路是:短时间 t 内的多次操作,我们只取这个时间 t 内的最后一次操作

所以节流的关键步骤就是:

  1. 当监听到一次操作,就 启动一个定时器 并 “关上大门flag = false
  2. 在定时器未完成计时内 阻止 往后的操作 if(!flag)
  3. 在定时器完成计时后 “打开大门flag = true
  4. 回到了第 1 步

效果:

节流后.gif

总结

防抖的思路是:短时间 t 内的多次操作,会舍弃掉前面的上一次的操作,等到时间 t 一过才将此次操作弹出

节流的思路是:短时间 t 内的多次操作,我们只取这个时间 t 内的最后一次操作

参考文章