大白话说防抖和节流

128 阅读4分钟

靓仔来了? 1.jpg

前言

最近写项目时写了个跳转顶部按钮,想着用防抖做做优化。

怎么个优化法呢,我们正常来说跳转顶部按钮你得做检测,检测页面滑动到一定高度时显示或者隐藏跳转顶部的按钮等等

微信图片_20230725150826.png

这个时候会发现,滑动一下直接就蹦出10条来了,哦吼,这不妥妥的浪费性能吗,要是多弄两下,稍微卡一点的电脑可能直接鼠标直接就螺旋爆炸了- -,这个时候用户就得去厨房给你拿钱了(美刀,还是人民匕),极差的用户体验自然不行,那怎么避免这个问题呢。


1.防抖(debounce)

为啥叫防抖,你看上面那个图,不做防抖的时候上下滑动是不是就像在一直抖一样,当然,这只是个比方,防抖的原理就是在一个规定的事件内无论触发多少次函数都只执行一次做到减少性能 就像这样:

// 防抖处理函数
const debounce = (detection,dates)=>{  // 两个参数分别需要防抖的函数和你要规定的时间
  let timer = null  // 先正常声明一下timer
  return function(){  // 把处理好的函数抛出去
    if(timer){		  // 如果timer有东西而不是null 的话就无限清除定时器	
      clearTimeout(timer)
    }
    timer = setTimeout(detection,dates)   // 这个时候因为你触发了之后在你规定的时间内
    					// timer是存在的所以上面的if判断会无限清除定时器
    					// 从而做到一个规定时间内无论你怎么触发都只触发一次的效果
  }
}
// 检测距离顶部多少并做相应处理
const showTop = () => {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log(scrollTop,'高度')
    if(scrollTop > 100){
      showDisplay.value = true
    }else{
      showDisplay.value = false
    }
}
// 跳转顶部
const goTop = () => {
  document.documentElement.scrollTop = 0
}
// 在挂载完成后进行防抖处理
onMounted(()=>{
  window.addEventListener("scroll", debounce(showTop,1000)); // 放入防抖处理后监听函数,并放入一秒的指定时间
})

2、节流(throttle)

那节流是咋回事呢,其实和防抖的概念大差不差,那节流的原理即为:执行完函数后在某一时间段内暂时失效,过了这段时间后重新激活,类似于技能冷却一样的。        只不过有时候需求有变化的时候做不同的处理,而且防抖处理后比如有个某个用户闲着没事拖着滚动条疯狂抽搐- -        那这个时候就会出BUG了,因为正常来说你的防抖逻辑是规定时间内触发一次,但是你不断滑动就会一直处在这个规定时间内导致一直在清除定时器导致无法触发setTimeout的函数,这个时候就要用节流了。        使用场景: 比如你组件的input框有个功能叫实时搜索,就是你输入一个值就去调接口搜索这玩意然后相应返回数据渲染结果,但是呢这搜索调接口的频率也是会比较消耗性能。        如果用防抖,那你非得等人家输入完了再去给反馈那这个实时就没用了嘛,那用户体验感是不行的,那你这个防抖很明显就不适合了,因为正常来说是输入了一个文字后执行一次搜索,然后进行执行冷却,即无论再输入什么都不重新调用接口搜索,冷却完了后在进行搜索,大概意思就是不管你输入的快慢,他都会在你调完一次接口后根据你指定的冷却时间进行冷却,冷却完了才能去调接口

const throttle = (detection,dates)=>{ // 与防抖一样 两个参数分别需要防抖的函数和你要规定的时间
  let burial = false		   // 设置一个冷却状态 初始为false
  return function(){       	   // 抛出
    if(burial){               // 如果冷却状态为true 就代表还在冷却,下面代码不执行
      return false
    }
    burial = true			  // 如果到这里了,变更冷却状态,等待定时器执行,等待定时器执行期间无限返回,以下代码不执行
    setTimeout(()=>{          // 等待完成,执行函数并且关闭冷却
      detection()
      burial = false
    },dates)
  }
}

如上面代码一样,当到了burial = true时,这个时候定时器还在等待执行,所以,这个时候无论你怎么触发都是不执行下面的定时器,不执行定时器burial一直都是true ,只有当规定时间到了,才回去执行定时器重置burial进行下一轮的循环

总结: 防抖:规定时间内频繁触发函数只有最后一次才会触发,就像监听滚动事件,你不断拉着滚动条上下上下,你会发现只有当你停止了之后才会触发函数。 节流:也是在规定时间内频繁触发函数,但是节流是第一次就触发了,触发完就进入冷却,然后再下一次触发,就像是一些轮播图一样,你会发现你无论点击多少次下一页他都是在规定的时间后才会到下一页。

以上说的不好,请见谅。