节流和防抖

节流:(事件n秒内被触发多次,则执行一次)

在规定的时间内无论触发多少次事件,在计时结束后都只触发一次(第一次或者最后一次 )的操作(滚动scroll, resize, 鼠标的mouseover mouseup, mousedown 事件等等)

有两种方式:常用的定时器还有时间戳判断; 规定时间是2000毫秒,scroll事件

1.定时器方式:

当触发事件的时候 先判断当前定时器是否为空, 如果非空 说明上一次的滚动事件定时器回调函数还未执行,就不需要再一次触发定时器; 如果为空,说明上一次的滚动事件中的定时器回调函数在2s内已经执行,并且清空了定时器,所以需要重新触发定时器,执行这一次的事件

this.timer = null
scrollHome(event) {
      // setTimeout 方式 节流 就是在规定的时间内 无论触发多少次事件,都只执行一次 ,执行完成之后 
      // 清空定时器,设置为Null ,
      if(!this.timer) { // 全局设置timer
          this.timer = setTimeout(() => {
            console.log(event)
            clearTimeout(this.timer)
            this.timer = null
          }, 2000)
      }
}

2. 时间戳的方式:

先定义一个全局的时间戳,用来记录上次执行函数的时间为0,当执行滚动事件时,首先先去执行后面的操作,然后记录lastTime和nowTime, 需要判断当前日期时间戳和那个全局的时间戳的间隔是否大于等于2000毫秒, 如果是则触发回调函数,设置上次触发回调函数的时间为now

// 第一次执行
this.lastTime = 0
scrollHome(event) {
      //  时间戳的方式
     let nowTime = new Date().getTime() //当前时间戳
      if(nowTime - this.lastTime >= 2000) {
         this.lastTime = nowTime 
         console.log(event) // 调用的函数
      }
    }


// 节流 利用闭包保留变量值 无论间隔期间有没有多次操作 每隔一段时间只触发一次 
export function throttle(fn, delay = 300) {
    let last = 0 // 上次触发时间
    return (...args) => {
        const now = Date.now()
        if (now - last > delay) { // 先执行 第一次就会执行
            last = now
            fn.apply(this, args)
        }
    }
}

防抖:(在事件触发n秒后被执行,如果在n秒之内又触发,则重新计时)

设置定时器, 如果在定时器启动之前,又触发了事件,那么定时器需要清空,重新计时;

 inputDebounce() {
      // 设置定时器, 如果在定时器启动之前,又触发了事件,那么定时器需要清空,重新计时
      // 每当事件被触发 则清除定时器
      if(this.debounceTime) {
        clearTimeout(this.debounceTime)
      }
        this.debounceTime = setTimeout(() => {
          console.log('输入文字')
        }, 2000)
    },


闭包形式
 function debounce(fn, delay) {
    let timer = null
    return function(...arg){
        if(timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(function() {
            fn.apply(this, arg)
        }, delay)
    }
}

但是有一个问题就是如果用户在启动定时器之前又触发了操作,重新计时,频繁这样操作,那么定时器任务就会一直延迟 ,也会造成问题, 导致定时器任务一直不执行;那么如何解决:
需要设置一个底线时间,就是我们的延迟时间,如果在定时器未启动之前频繁操作,在延迟时间之前的操作都可以重新设置定时器

// debounce 利用闭包保留变量值 防止短时间内多次点击 在间隔时间内如果再次触发,则重新计算时间(查询或者提交)需要和节流结合 防止极端情况: 一直点击 事件一直不触发 
export function debounce(fn, delay = 300) {
    let last = 0
    return (...args) => {
        const now = Date.now()
        if (now - last < delay) { // 需要有一个时间底线
            if (this.debounceTimer) {
                clearTimeout(this.debounceTimer)
            }
            this.debounceTimer = setTimeout(() => {
                fn.apply(this, args)
                clearTimeout(this.debounceTimer)
            }, delay)
        } else { // 到达了时间底线 自动执行回调函数
            last = now
            fn.apply(this, args)
            clearTimeout(this.debounceTimer)
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值