防抖与节流总结

最近复习到了防抖与节流,今天就把防抖与节流给总结一下吧。

防抖

什么是防抖

防抖是一种常用的前端优化技术,它可以有效地减少在用户频繁触发某些事件(比如鼠标滚动、窗口缩放等)时产生的多次执行函数的问题。这样可以避免函数被频繁调用,从而提高页面的性能和用户体验。

什么时候使用防抖

  1. 输入框搜索:在用户输入关键字搜索时,若是有着自动补全事件,防抖就可以避免频繁请求,提高搜索效率。
  2. 按钮点击:在按钮被连续点击时,防抖函数可以避免重复触发事件,从而避免页面卡死以及产生不可预期的后果,提高用户体验。
  3. 页面滚动:在页面滚动时,避免频繁地触发滚动事件,提高性能和体验。
  4. 窗口缩放:在窗口大小发生改变时,避免频繁地触发事件,等待窗口调整完成后,再执行resize事件中的代码,提高性能和体验。
  5. 表单验证:在表单验证时,避免频繁地触发验证事件,提高效率和体验。

防抖的实现原理

定时器实现防抖是在事件触发后设定一个延时时间,在这个时间内如果再次触发了同样的事件,就会重新开始计时,直到延时时间结束后才会执行函数。

防抖函数的代码

function debounce(fn,delay){
    let timer = null;
    return function(){
        let context = this;
        let args = arguments;
        if(timer){
            clearTimeout(timer);
            timer = null;
        }
        timer = setTimeout(()=>{
            fn.apply(context,args);
        },delay);
    }
}

这里传入的参数fn是我们需要处理的函数,delay是我们设定的延时时间。

防抖的缺陷

  1. 无法立即执行函数,需要等待一定的时间后才能执行。

  2. 如果在等待时间内再次触发函数,就会重新计时,可能会导致函数执行的次数少于期望值。

  3. 如果设置的时间过长,会导致用户等待过久,降低用户体验。

节流

什么是节流

节流是一种优化性能的技术,主要用于减少某些事件的触发频率。在一些需要频繁触发事件的场景中,如果不加以限制,可能会造成系统负载过高,甚至导致卡顿或崩溃。节流技术就是通过限制事件触发的频率,来减少系统负载,提高性能。常见的节流方式包括定时器节流和时间戳节流。

什么时候使用节流

  1. 频繁的鼠标移动、滚动事件:比如浏览器滚动条的滚动、鼠标移动、拖拽等操作,会频繁触发事件,使用节流可以减少事件的触发次数。

  2. 窗口大小改变事件:当用户调整浏览器窗口大小时,会触发窗口大小改变事件,这个事件会在用户停止调整窗口大小后才会触发,因此使用节流可以减少事件的触发次数,提高性能。

  3. 输入框输入事件:比如用户在输入框中输入文字时,会触发输入事件,如果用户连续输入多个字符,会频繁触发事件,使用节流可以减少事件的触发次数,提高性能。

  4. 搜索框搜索事件:用户在搜索框中输入关键字进行搜索时,搜索框会频繁触发搜索事件,使用节流可以减少事件的触发次数,提高性能。

  5. 延迟加载:在滚动到页面底部时,可以使用节流控制请求的频率,减少服务器的压力和网络带宽的消耗。

  6. 防止重复提交:比如用户连续多次点击提交按钮,会触发多次提交事件,使用节流可以减少事件的触发次数,避免重复提交。

节流的实现原理

时间戳实现节流

时间戳实现节流的原理是在触发事件时,记录一个时间戳,然后每次触发事件时都与上一次记录的时间戳进行比较,如果时间间隔大于等于指定的时间间隔,则执行函数并更新时间戳。如果时间间隔小于指定的时间间隔,则不执行函数。

定时器实现节流

定时器实现节流的原理是在执行时创建一个定时器,定时器到期则执行函数,并将变量置为null。在此期间如果再次触发节流函数,则判断定时器是否为空,为空则重新创建一个定时器,否则直接返回。

节流函数的代码

时间戳实现节流

// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval) {
    // last为上一次触发回调的时间
    let last = 0
    // 将throttle处理结果当作函数返回
    return function () {
        // 保留调用时的this上下文
        let context = this
        // 保留调用时传入的参数
        let args = arguments
        // 记录本次触发回调的时间
        let now = +new Date()
        // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
        if (now - last >= interval) {
            // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
            last = now;
            fn.apply(context, args);
        }
    }
}

定时器实现节流

function throttle(fn,interval){
    let timer = null;
    return () => {
        if(timer)return;
        timer = setTimeout(()=>{
            fn();
            timer = null;
        },interval);
    }
}

节流函数的缺陷

节流函数无法完全避免事件的重复执行,它只是降低了重复执行的频率。因此,在某些场景下,可能需要使用防抖函数来完全避免事件的重复执行。

节流与防抖的融合

不难发现,节流函数和防抖函数都有着各自的缺陷,因此我们可以将节流与防抖融合起来,在防抖中加入节流的思想,避免遇到急躁的用户持续触发事件,导致用户等待过久,降低用户体验的问题。

function throttle(fn, delay) {
  // last为上一次触发回调的时间, timer是定时器
  let last = 0, timer = null
  // 将throttle处理结果当作函数返回
  return function () { 
    // 保留调用时的this上下文
    let context = this
    // 保留调用时传入的参数
    let args = arguments
    // 记录本次触发回调的时间
    let now = +new Date()
    // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
    if (now - last < delay) {
    // 如果时间间隔小于我们设定的时间间隔阈值,则为本次触发操作设立一个新的定时器
       clearTimeout(timer)
       timer = setTimeout(function () {
          last = now
          fn.apply(context, args)
        }, delay)
    } else {
        // 如果时间间隔超出了我们设定的时间间隔阈值,那就不等了,无论如何要反馈给用户一次响应
        last = now
        fn.apply(context, args)
    }
  }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Uniapp中,是用来控制频繁触发事件的常用技术。是指在频繁触发某一个事件时,一段时间内或者一定条件下不再触发该事件对应调用的函数。的实现方式是设置一个定时器,在事件触发后延迟一定时间执行函数,如果在该时间段内再次触发事件,就清除之前的定时器并重新设置一个新的定时器,以此来保证只触发最后一次事件。 举个例子,在Uniapp中实现的代码如下: ```javascript export default { data() { return { fdFlag: null } }, methods: { fd() { let that = this clearTimeout(this.fdFlag) this.fdFlag = setTimeout(() => { that.fdDoing() this.fdFlag = null }, 800) }, fdDoing() { console.log('事件触发') } } } ``` 上述代码中,当按钮被点击时,会调用fd方法,在800毫秒的时间段内,如果再次点击按钮,会清除之前的定时器并重新设置一个新的定时器,最终只有最后一次点击会触发fdDoing方法。这样就实现了止按钮多次连续点击的效果。 而是在一个时间段内仅能触发一次事件,但到了下一个时间段,也会再次触发一次事件。的实现方式是设置一个标志位,通过控制该标志位的状态来决定是否触发事件。当事件被触发时,首先检查标志位的状态,如果标志位为false,则表示在规定的时间内已经触发过事件,不再执行后续代码;如果标志位为true,则表示可以执行事件处理函数,并在执行后将标志位设置为false,以此来控制事件的触发频率。 举个例子,在Uniapp中实现的代码如下: ```javascript export default { data() { return { jlFlag: true } }, methods: { jl() { let that = this if (!this.jlFlag) { return } this.jlFlag = false setTimeout(() => { that.jlDoing() this.jlFlag = true }, 2000) }, jlDoing() { console.log('事件触发') } } } ``` 上述代码中,当按钮被点击时,会调用jl方法,在2秒的时间段内,如果再次点击按钮,由于jlFlag为false,所以不会执行后续代码;等到2秒时间过去后,jlFlag会重新设置为true,下次点击按钮时,又会执行jlDoing方法。这样就实现了每2秒触发一次事件的效果。 总结起来,Uniapp中的技术都是为了控制频繁触发事件而设计的。通过延时执行函数来保证只触发最后一次事件,而通过设置标志位来控制事件的触发频率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值