截流和防抖

328 阅读3分钟

最近身体疲惫,每天感觉脑子跟不上,并且很容易犯困,还好有人一直给充电,本来不太精神但是瞬间就充满能量。经过一番思想斗争之后,终于决定昨天鸽了一下,哇,真的好爽,今天早上来了还被嘲讽提前过上了公园大爷的生活,哈哈哈,不过休班一时爽,一直休班一直爽啊 ,不不不,说错了,一直休班木有qian啊,最近怎么话这么多,步入正题吧,今天来研究一下截流和防抖原理。(接着奏乐,接着舞)

  1. 什么情况出现的截流和防抖

    • 当我们在鼠标移动和页面滚动的时候频繁的触犯一个函数
    • 当属一个输入框中,输入进行查询的时候
    • 屏幕尺寸发生改变的时候(一直在缩小放大浏览器)

    以上情况都会高频的触发函数,这个时候浏览器就容易卡死,难道这样就放任不管么?兄弟你不是在开玩笑吧?怎么可能不管呢。这属于前端的性能优化之一啊。

  2. 防抖原理和实现

    • 原理:什么是防抖呢?顾名思义那就是防止抖动啊,在你一直抖啊抖的过程,不在你抖动的时候进行操作,而是再你稳定之后进行函数的执行,也就是说,当你频繁的进行一个动作(下拉滚动条),不会一直执行所触发的函数而是在停下来之后多长时间进行触发。再来举个栗子,哎!每天举栗子也很沉的好嘛,咱们那种大厦的感应的门了解吧?比如现在有10个人一直进门(好比你一直在滚动页面),这个感应门不可能进一个人关一次门吧?这样门早就被砸了好么(浏览器奔溃了),感应门肯定是等10个人进去了,等几(比如10秒)秒,这10秒内没有人进了,就执行关门这个操作(触发的函数),10内有人进,就重新再记10秒重新计算。这就是防抖

    • 实现思路 :主要有两点 1.事件发生后,清除旧的计时器 2.设置行的计时器

      <div class="box"></div>
      <script>
        var box = document.querySelector('.box');
         function debounce(handler,time){
                  var timer = null ;         
                  return function (){
                      clearTimeout(timer);    // 触发就清0 触发就清0 ; 直到不触发之后,几秒钟 
                      var args = arguments;
                      var _this = this;
                      timer  = setTimeout(function(){
                          // 把box对象的这个this传给它
                          handler.apply(_this,args);
                      },time);
                      
                  }
              }
        // 要执行的动作 
        function handle(e){
          console.log("这里做点什么");
          this.innerHTML = e.clientX;  
      
        }
        var testDebounce  = debounce(handle,2000); 
        box.onmousemove = testDebounce;
      </script>
      

      我觉得你肯定你开始的时候一定和我一样,为什么debounce函数要return 一个函数,那我们来写一下

      var timer = null;
      box.onmousemove = reTime();
      function reTime (){
        if(timer){
          clearTimeout(timer);
        }
        timer  = setTimeout(handle,2000)
      }
      function handle(){
        // todo somethings
      }
      

      reTime函数需要操作来自父级作用域的变量timer,而debounce函数就是为了创建这样一个作用域,使得每次执行reTimer函数时timer变量都是存在的。但是后边这种相对于前边就不那么优雅了,第一个timer只在函数内部进行使用,不必在全局变量中,显然闭包更符合方案。

  3. 截流原理和实现

    • 原理:知道了防抖,截流就是更简单了,在一个瀑布中,定时抽断一下,俗话讲抽刀断水水更流,不形容我们做程序哈。再来举一个吧,光举着也没人吃。比如我们正在做一个输入框,要求每输入一个字符都调用一个API来查询数据,从而实现联想、自动补全等功能,然而我们的输入速度是很快的,可能还没等第一个字符的查询结果出来,第二个字符就已经敲进去了,所以我们需要让查询频率小一点,具体做法就是在输入的过程中,每隔N秒才查询一次。

    • 实现思路 :确保一个计时器停止时再重新计时

      <div class="box"></div>
      <script>
          var box = document.querySelector(".box");
      
              function throttle(fn,delay){
                  let timer = null ; 
                  return function throttler(){
                      if (timer===null) {  // 只要时间不是null 就触发 。也就是说这个事件触发之后就从头算时间,到时间了也就再次触发
                          timer = setTimeout(function(){
                              fn();
                              timer = null;
                          },delay)
                      }
                  }
              }
              function handle(){
                  console.log('--todoSomethings---')
              }
              box.onmousemove = throttle(handle,2000)
      </script>