zoukankan      html  css  js  c++  java
  • 04-防抖和节流

    先简明扼要概括一下:

    -- 区别:

    函数防抖是单位时间内只执行一次;

    函数节流是间隔时间执行,不管事件触发有多么的频繁,都会保证在规定时间内执行一次真正的事件处理函数。


     

    -- 原理:

    防抖是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,都会清除当前的 timer 然后重新设置超时调用,即重新计时。这样一来,只有最后一次操作能被触发

    节流是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。


     

    防抖:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <title>Document</title>
      <style>
        body{
          height: 3000px;
        }
      </style>
    </head>
    <body>
        <input type="text" id="inp">
    </body>
    </html>
    
    <script>
    let oInp=document.getElementById('inp');
    function nice(fn,time){
      let timer =null;
      return arg=>{
          clearTimeout(timer);
          timer=setTimeout(()=>{
            fn.call(this,arg)
          },time)
      }
    }
    let getFn = nice(ajax,1000);
    function ajax(data){
      console.log(data,"我拿到数据了");
    }
    
    // 键盘事件
    oInp.addEventListener('keyup',(e)=>{
      getFn(e.target.value)
    });
    
    // 滚动条滚动事件
    document.body.onscroll=function(e){
      getFn(e.timeStamp)
    }
    
    </script>

    节流:(包含了防抖)

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <title>Document</title>
      <style>
        body{
          height: 3000px;
        }
      </style>
    </head>
    <body>
        <input type="text" id="inp">
    </body>
    </html>
    
    <script>
    let oInp=document.getElementById('inp');
    function nice(fn,time){
      let last, 
          timer =null;
      return arg=>{
        // 每次操作事件(滚动/输入)触发时,都会得到一个最新的时间毫秒数
        let now = Date.now();
        //如果上一次存在(有操作)并且上一次的时间+定时器间隔时间 > 现在的时间,说明现在这个操作是在我定时器触发的时间内的,
        if(last && last + time > now){
          // 那么下一次再进来,就要清除之前的定时器,重新计时。这是做了防抖
          // 那就把之前的定时器清除重新计时,1S后执行函数。
          clearTimeout(timer);
          timer=setTimeout(()=>{
            last=now;    // 每次重新更新上一次的时间,这样在定时器间隔时间内,last+time 就会永远> now,造成if条件恒成立,也就会1秒执行一次事件函数
            fn.call(this,arg)
          },time)
        }else{   //初始状态或操作间隔>定时器时间(1s),就会立即执行(ajax函数)
          last = now;   // 每次重新更新上一次的时间
          fn.call(this,arg)
        }
      }
    }
    let getFn = nice(ajax,1000);
    function ajax(data){
      console.log(data,"我拿到数据了");
    }
    
    // 键盘事件
    oInp.addEventListener('keydown',(e)=>{
      getFn(e.target.value)
    });
    
    // 滚动条滚动事件
    document.body.onscroll=function(e){
      getFn(e.timeStamp)
    }
    
    </script>

    以上代码可以运行一下去感受一下。

     vue中使用:

    <template>
      <div class="box">
        <el-input @keydown.native="keyDownFn" type="text" v-model="value"/>
      </div>
    </template>
    <script>

    export default {
      data () {
       return {
         value:'',
         timer :null,
         now:'',
         last:'',
        }
      },
      methods:{ 
        keyDownFn(e){
          let getFn =  this.nice(this.ajaxFn,1000);
          getFn(e.target.value);

        },
        nice(fn,time){
          return arg=>{
            this.now = Date.now();
            if(this.last && this.last + time > this.now){
              clearTimeout(this.timer);
              this.timer=setTimeout(()=>{
                this.last=this.now;   
                fn.call(this,arg)
              },time)
            }else{   
              this.last = this.now;   
              fn.call(this,arg)
            }
          }
        },
        ajaxFn(data){
          console.log(data,'我拿到数据了');
        }
      },
    }
    </script>
    <style>
    .box{
      padding: 100px;
    }
    </style>

     

    参考:

    https://zhuanlan.zhihu.com/p/51608574


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5     <meta charset="UTF-8">
      6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
      7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
      8     <title>防抖节流</title>
      9     <style>
     10 
     11     </style>
     12 </head>
     13 
     14 <body>
     15     <div>
     16         防抖:<input type="text" id="inp1">
     17     </div>
     18     <div>
     19         节流:<input type="text" id="inp2">
     20     </div>
     21     <div>
     22         节流(第一次直接拿到数据):<input type="text" id="inp3">
     23     </div>
     24 </body>
     25 
     26 </html>
     27 <script>
     28     var oInp1 = document.getElementById("inp1");
     29     var oInp2 = document.getElementById("inp2");
     30     var oInp3 = document.getElementById("inp3");
     31 
     32     // 防抖
     33     function debonce(fn, delay) {
     34         var timer = null;
     35         return (() => {
     36             clearTimeout(timer)
     37             timer = setTimeout(() => {
     38                 fn()
     39             }, delay)
     40         })
     41     }
     42 
     43     // 模拟接口ajax获取到的数据
     44     function getData1() {
     45         console.log(Math.random());
     46     }
     47     var fn1 = debonce(getData1, 500);
     48     oInp1.addEventListener('keydown', fn1);
     49 
     50     // ------------------------------------------------------------------------------------------------------
     51     function getData2(data) {
     52         console.log(data);
     53     }
     54 
     55     // 节流
     56     function throttle1(fn, delay) {
     57         var timer = null;
     58         var oldTime = Date.now();
     59         return (arg) => {
     60             var nowTime = Date.now();
     61             if (nowTime - oldTime > delay) {
     62                 clearTimeout(timer)
     63                 oldTime = nowTime;
     64                 timer = setTimeout(() => {
     65                     fn.call(this, arg);
     66                 }, delay)
     67             }
     68         }
     69     }
     70 
     71     var fn2 = throttle1(getData2, 1000);
     72     oInp2.addEventListener('keyup', (e) => {
     73         fn2(e.target.value)
     74     });
     75     // ------------------------------------------------------------------------------------------------------
     76 
     77     function getData3(data) {
     78         console.log(data);
     79     }
     80 
     81     // 节流2  -> 上次发生事件的时间+定时器间隔时间<现在的时间,证明过期了,就直接取到数据
     82     function throttle2(fn, delay) {
     83         var timer = null;
     84         var oldTime = null;
     85         return (arg) => {
     86             var nowTime = Date.now();
     87             if (oldTime && oldTime + delay > nowTime) {
     88                 clearTimeout(timer)
     89                 timer = setTimeout(() => {
     90                     oldTime = nowTime;
     91                     fn.call(this, arg);
     92                 }, delay)
     93             } else {
     94                 oldTime = nowTime;
     95                 fn.call(this, arg);
     96             }
     97         }
     98     }
     99 
    100     var fn3 = throttle2(getData3, 1000);
    101     oInp3.addEventListener('keyup', (e) => {
    102         fn3(e.target.value)
    103     });
    104 </script>
  • 相关阅读:
    uboot的仓库在哪里?
    git如何查看执行过的历史git命令
    for(;;)和while(true)的区别
    CountDownLatch的理解和使用
    countDownLatch
    websocket @ServerEndpoint(value = "/websocket/{ip}")详解
    Java原子性操作之——Atomic包的原理分析
    CAS原理
    java线程池ThreadPoolExecutor的keepAliveTime=0时,表示超过core线程数的线程在空闲时立即结束!!!
    ThreadPoolExecutor 线程池Demo
  • 原文地址:https://www.cnblogs.com/haoqiyouyu/p/14551182.html
Copyright © 2011-2022 走看看