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>
原文地址:https://www.cnblogs.com/haoqiyouyu/p/14551182.html