防抖和节流

1. 引入场景

  1. 监听浏览器滚动条的位置,会发现这个函数的执行频率太高了。
  2. 函数防抖和节流,都是控制事件触发频率的方法。应用场景有很多,输入框持续输入,将输入内容远程校验、多次触发点击事件、onScroll等等。
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
window.onscroll  = showTop
复制代码

2. 防抖(debounce)

1. 思路: 在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:

  • 如果在200ms内没有再次触发滚动事件,那么就执行函数
  • 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时

可以理解为:比如送外卖,接到一单后,开始计时,如果5分钟内又收到一单,就重新计时5分钟。直到5分钟没有收到信订单,再送货。

2. 代码

防抖重在清零 clearTimeout(timer)

// 防抖函数
function debounce(fn, delay){
    let timer = null // 计时
    return function() {
        if (timer) { // 如果已经开始计时了,就清除计时
            clearTimeout(timer)
        }
        // 重新开始计时,delay后执行函数,然后将定时器清空
        timer = setTimeout(()=>{
            fn()
            timer = null
        },delay)
    }
}
// fn
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
// 使用防抖
window.onscroll = debounce(showTop,1000)
复制代码

对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次

4. 应用

  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存

3. 节流(throttle)

  • 用防抖的方案的结果是:用户如果不断触发,就永远不会执行。
  • 我们想即使用户不断触发,也能在某个时间间隔给出反馈。
  • 所以引入了节流

1. 思路

类似阀门一样,定期开发,就是函数执行一次后,在一个时间段内失效,过了这段时间才能再次执行。

2. 代码

节流重在开关锁 flag=true/false

function throttle(fn ,delay){
    let flag = true //是否在工作状态
    return function (){
        if( !flag){//不在工作状态,即处于冷冻状态,不执行函数
            return 
        }
        flag = false
        setTimeout(()=>{
            fn.call(this,arguments)
            flag = true
        },delay)
    }
}
// 以下照旧
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop,1000)
复制代码

3. 应用

  • scroll 事件,每隔一秒计算一次位置信息等
  • 浏览器播放事件,每个一秒计算一次进度信息等
  • input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖)
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享