一篇文带你切底搞懂防抖和节流

62 阅读4分钟

在前端开发的过程中,我们经常绑定一些持续触发的事件,比如resize,scroll,mousemove等相关事件,但有些时候,我们并不希望在你这些事件持续触发的过程中频繁的去执行事件处理函数。

如果在开发中遇到这样的问题,你会怎么解决的呢!那我说说我的解决办法,我一般都会使用防抖和节流来解决它。

那么什么是防抖?什么是节流?接下来认真看完这一下内容,婧婧带你了解学习防抖,节流是什么,以及如何利用防抖和节流解决频繁调用事件处理函数的现象。

我们先来了解下防抖吧

防抖

防抖:主要是控制次数,函数的执行的次数

比如:清除定时器、input验证、搜索联想、window.onresize事件都可以使用防抖来避免频繁执行。

思路

首次运行时把定时器赋值给一个变量,第二次执行时,如果间隔没超过定时器设定的时间则会清除掉定时器,重新设定定时器,依次反复,当我们停止下来时,没有执行清除定时器,超过一定时间后触发回调函数。

解决封装动画函数多个动画叠加的问题

在开启一个新的定时器之前先清除定时器,这样动画效果就不会叠加了

  • 原本代码

    开启多个定时,执行动画,会导致动画叠加

    function animation(){
      var timer = setInterval(()=>{
        //...
      },100)
    }
    // 调用animation函数,会开启定时器,如果点击间隔时间在100毫秒之类,就会导致多个定时器同时执行动画
    window.onclick = function(){
      animation();
    }
  • 防抖改写animation函数
    var timer;
    function animation(){
      // 开启定时器之前把现有的定时器先清除,保证一个功能只存在一个定时器去执行动画
      clearInterval(timer)
      timer = setInterval(()=>{
        //...
      },100)
    }

解决表单延迟验证

如果300ms以内再次触发keyup事件就清除定时器,只有最后一次输入才会触发验证。

  • 原本代码

    会同时触发多个keyup事件。都会去验证表单,如果涉及到http请求,就很好性能

    input.onkeyup = function () {
      //... 表单验证逻辑代码
    }
  • 防抖改写
    input.onkeyup = function () {
      // 触发keyup事件300毫秒之后再去验证,如果同时触发多个keyup事件,清除前面的定时,只执行最后一次触发的验证
      clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        // ...验证逻辑...
      }, 300)
    }

节流

节流:主要是控制执行频率

比如:scroll、mousemove事件都可以使用节流来限制执行的频率

思路

先设定一个变量值为true,执行这个函数时,判断变量的值是否位true,则直接return,不执行函数中的代码,否则继续执行函数中代码

当执行函数中代码后,把变量设置为false。那么下次判断变量时则为false。

解决滚动加载更多数据

当请求数据列表,如果数据很多,我们通常会采用分页请求的形式,分页一般有分页按钮和滚动加载更多数据的形式

  • 原本代码

    滚动事件则是持续性触发的,如果在滚动事件中发送ajax请求,则会导致同时会发送多个ajax请求

      // 如果滚动到底部了 则发送ajax请求加载更多数据
      if(scrollY >= document.body.clientHeight-innerHeight){
        // ajax() 请求数据
      }
    }
  • 节流改写

    预设flag变量 表示请求数据的状态,false表示还在请求数据,true表示请求完成

    滚动到底部可以根据flag来判断是否可以发送ajax请求数据

    如果flag为true,则可以发送ajax请求,设置flag=false,flag为false则不发送ajax请求

    当数据请求完成需要把flag设置为true

    var flag = true;
    window.onscroll = function(){
      // 如果滚动到底部了 则发送ajax请求加载更多数据
      if(scrollY >= document.body.clientHeight-innerHeight ){
        if(flag == false){
          return;
        }
        flag = false;// 表示正在请求数据来
        // ajax() 请求数据,请求完成需要把flag设置为true
      }
    }

总结

防抖: 将多次操作合并为一次操作进行,原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置,这样就只有最后一次的操作能被触发了。

节流: 使得一定时间内只触发一次,原理是通过判断是否达到规定的时间再次触发了,如果没有达到规定的时间,是不会去执行对应的代码

防抖和节流的区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。