前言

在进行窗口的操作或者输入框操作时,如果事件处理函数用的频率无限制,会加重浏览器和服务器的负担,此时我们就可以用防抖(debounce)和节流(throttle)的方式来减少调用频率,同时又不影响实际效果。

什么是防抖和节流?

防抖:在设定的时间内触发一次事件,会在设定的时间结束之后执行该事件处理程序,如果在设定的时间内多次触发事件,则每次触发事件都会重新计时。(可以将防抖类比成电梯:第一个人进电梯之后,电梯会在5秒之后自动关闭电梯门,如果在这5秒内又有人进来了,那么电梯会重新等待5秒后再关门。)

简单理解就是:单位时间内,频繁触发一个事件,以最后一次触发为准。

节流:在设定的时间内多次触发事件,只会在设定的时间结束后执行一次。

简单理解就是:单位时间内,频繁触发一个事件,只会触发一次。

防抖的应用场景:
主要用来监听input输入框:我们在搜索内容的时候一般都会有搜索提示,它是通过input事件获取用户输入的内容,然后发送数据请求给后端,后端返回搜索提示内容。我们希望等待用户输入结束之后再发送请求,而不是输入一个发一次请求,这时候就需要使用防抖函数来实现。

节流的应用场景:

监听scroll滚动事件、按钮点击等等

如何实现防抖和节流?

防抖主要使用定时器来实现:

//func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
    function debounce(func, delay){
      var timer = null;
      return function(){
        var that = this;
        var args = arguments
        //每次触发事件 都把定时器清掉重新计时
        clearTimeout(timer)
        timer = setTimeout(function(){
          //执行事件处理程序
          func.call(that, args)
        }, delay)
      }
    }

例子:

(1)不使用防抖函数:

<body>
  <input type="text">
  <script>
    var inp = document.getElementsByTagName('input')[0]
    //获取输入框的输入内容
    inp.oninput = function(){
      console.log(this.value);
    }
  </script>
</body>

JS防抖和节流

(2)使用防抖函数:

<body>
  <input type="text">
  <script>
    function debounce(func, delay){
      var timer = null;
      return function(){
        var that = this;
        var args = arguments
        clearTimeout(timer)
        timer = setTimeout(function(){
          func.call(that, args)
        }, delay)
      }
    }
    var inp = document.getElementsByTagName('input')[0]
    function handler(){
      console.log(this.value);
    }
    inp.addEventListener('input', debounce(handler, 1000))
  </script>
</body>

JS防抖和节流

节流的实现有两种方式:

1、使用时间戳实现

//func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
    function throttle(func, delay){
      //定义初始时间(开始触发事件的时间)
      var start = 0;
      return function(){
        var that = this;
        var args = arguments;
        //获取当前时间戳
        var current = Date.now();
        // 判断当前时间与初始时间是否超过间隔
        if(current - start >= delay){
          //执行事件处理程序
          func.call(that, args)
          //更新初始时间
          start = current;
        }
      }
    }

2、使用定时器实现

function throttle(func, delay){
      var timer = null;
      return function(){
        var that = this;
        var args = arguments
        if(!timer){
          timer = setTimeout(function(){
            //执行事件处理程序
            func.call(that, args)
            //事件执行完后把定时器清除掉,下次触发事件的时候再设置
            timer = null;
          }, delay)
        }  
      }
    }

例子:

(1)不使用节流函数

<body>
  <div style="height: 500px; width: 300px; background-color: rgb(244, 199, 207);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(239, 131, 16);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(11, 66, 194);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(177, 21, 244);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(75, 180, 115);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(163, 122, 150);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(39, 34, 35);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(209, 218, 40);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(63, 179, 215);"></div>
  <script>
    function handler(){
      console.log('页面发生了滚动');
    }
    document.addEventListener('scroll', handler)
  </script>
</body>

JS防抖和节流

(2)使用节流函数

<body>
  <div style="height: 500px; width: 300px; background-color: rgb(244, 199, 207);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(239, 131, 16);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(11, 66, 194);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(177, 21, 244);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(75, 180, 115);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(163, 122, 150);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(39, 34, 35);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(209, 218, 40);"></div>
  <div style="height: 500px; width: 300px; background-color: rgb(63, 179, 215);"></div>
  <script>
    function throttle(func, delay){
      var timer = null;
      return function(){
        var that = this;
        var args = arguments
        if(!timer){
          timer = setTimeout(function(){
            //执行事件处理程序
            func.call(that, args)
            //事件执行完后把定时器清除掉,下次触发事件的时候再设置
            timer = null;
          }, delay)
        }  
      }
    }
    function handler(){
      console.log('页面发生了滚动');
    }
    document.addEventListener('scroll', throttle(handler, 1000))
  </script>
</body>

 JS防抖和节流

发表回复