浏览器防抖和节流

浏览器防抖和节流

鉴于在测试代码过程中滚动滚动条之后在控制台打印了一万条日志,本人决定好好学习一下防抖和节流,以下均为个人学习记录(这瓜不保熟),有错误欢迎指正

举个栗子

开发网站时,常常会有这样一个需求,网站右下角需要在滑动一定距离后出现一个”回到顶部“的按钮,方便用户操作。要实现这个功能,方法也很简单,监听浏览器的滚动事件,当滚动距离达到自己需要的距离时,让右下角的按钮出现,并固定定位在右下角,直接上关键代码。

function showTop  () {
  let sTop = document.body.scrollTop || document.documentElement.scrollTop
  console.log('滚动条位置:' + sTop)
 if (sTop >= '所需的距离') { /* 这里去触发出现按钮的事件以及设置样式 */}
}
window.onscroll  = showTop

但是这样处理,也会造成另外一个问题——触发频率过高
可以预见,每次滚动一点点,就会触发多次这个事件,消耗了浏览器的性能,这并不是我们想要的结果,这个时候就可以使用防抖节流优化这种场景

防抖

为了处理上面遇到的问题,基本思路就是降低事件触发的频率,所以第一种方案就应运而生了,我们可以让事件在一段时间内只触发一次。简易的方案如下:当第一次触发事件时,我们不去立即触发事件处理函数,而是给出一段时间,这时候会有两种情况

  • 若在这段时间内事件没有再次触发,那么就可以在时间结束后调用该处理函数
  • 若在这段时间内事件再次触发了,那么重新开始计时,在这段时间中观察后续事件是否触发

听起来是不是很像定时器的功能呢?没错,就是使用定时器。通过计时器,我们就可以让事件在一定时间之后触发一次。借助参考资料大佬的思路,这里使用闭包来举例

function debounce(fn,delay){
  let timer = null // 只执行一次
  return function() {
    if(timer){ // 多次触发定时器时先清除掉上一个
      clearTimeout(timer) 
    }
    timer = setTimeout(fn,delay)
  }
}
// 实际的处理事件
function showTop  () {
  var sTop = document.body.scrollTop || document.documentElement.scrollTop
  console.log('滚动条位置:' + sTop)
  if (sTop >= '所需的距离') { /* 这里去触发出现按钮的事件以及设置样式 */}
}
window.onscroll = debounce(showTop,2000) // 设置间隔

执行代码后我们会发现,原来小小拖动就造成一万行打印的现象,变成了只打印一行,执行实际结果是进行滑动2000ms后,控制台才会打印出当前距离顶部的滑动距离,且只打印一次,这其实就实现了防抖,现在可以结合例子来理解防抖的含义了:

  • 对于短时间连续触发的事件,防抖的含义就是让某个时间期限内,事件处理函数只触发一次

需要注意的是,上面这个例子,实际上滚动过程中也不断触发了debounce函数,但是相比真正的处理事件showTop,防抖函数的处理和消耗要少得多,所以也达到了优化的效果。

节流

上面的防抖已经初步达到了减少滑动处理事件的频率,但是事情就这样结束了吗?
在这里插入图片描述
真正试着去运行上面这段代码的话,会发现存在一个现象,你如果一直拖拽滚动条而不放开(别问为什么,问就是需求),控制台是永远不会打印出东西的,这是因为定时器一直没有结束(多次触发防抖时会清除掉上一次的定时器并开启另一个定时器)。这对于某些业务场景是不合适的,所以还需要考虑另外一种方案,比如能不能在某段时间内触发一次后就禁止触发,等过了这段时间后再恢复可触发状态呢?事实上是可以的,而且只需要在防抖的代码上进行一点修改就可以达到效果,如下:

function throttle(fn,delay){
  let flag = true // 只执行一次
  return function() {
    if(!flag){ // 处于已生效状态则不触发
      return false;
    } 
    flag = false // 开始生效
    timer = setTimeout(() => {
      fn()
      flag = true // 恢复可触发状态
    }, delay)
  }
}
// 实际的处理事件
function showTop  () {
  var sTop = document.body.scrollTop || document.documentElement.scrollTop
  console.log('滚动条位置:' + sTop)
  if (sTop >= '所需的距离') { /* 这里去触发出现按钮的事件以及设置样式 */}
}
window.onscroll = throttle(showTop,2000) // 设置间隔

上面的代码的结果,就变成了一直拖着滚动条时,控制台会以2000ms为间隔周期性输出结果,而这个就是节流的一种实现方式。现在可以给出节流的定义:

  • 对于连续触发的事件,节流的含义就是让事件处理函数在一定的时间间隔周期性触发

实际上,这只是节流的一种实现方式,不过只要掌握了节流的概念就不难写出相关的处理,这里就不一一列举

总结

防抖和节流都是为了减低浏览器触发事件的频率,提高利用率的方式,具体使用哪一种需要依据业务场景来定,比如搜索框的联想可以设定间隔一定时间后触发一次搜索、而页面重绘可以在最后进行触发,这里就分别可以用上节流和防抖。

参考资料

参考链接
感谢链接中的文章给予的参考,本文纯根据个人需求进行截取摘录以防工作中需要,如要更详尽的了解相关内容,可点击参考链接

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值