防抖和节流

防抖

所谓防抖,就是指触发事件后,函数在 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间

简单的说,当一个函数连续触发,只执行最后一次。

函数防抖一般用在什么情况之下呢?一般用在:连续的事件只需触发一次回调的场合。

具体有:

  1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
  2. 用户名、手机号、邮箱输入验证;
  3. 浏览器窗口大小改变后,只需窗口调整完后,再执行resize事件中的代码,防止重复渲染。

代码实现:

<div class="box"></div>

<style>
  .box {
    width: 100px;
    height: 100px;
    background-color: pink;
  }
</style>

防抖函数封装:

// fn是要调用的函数,wait是等待的时间,immediate是第一次是否立即执行
function debounce(fn, wait, immediate) {
  let timerID = null;
  // 返回一个闭包函数,用闭包保存timerID确保其不会销毁,重复点击会清理上一次的定时器
  return function () {
    const context = this; // this依然指向原来的函数
    // console.log(this); // this指向触发事件的对象<div class="box"></div>
    const args = [...arguments]; // 不同的函数会有不同的参数传入,保存事件参数
    // console.log(arguments); // Arguments[MouseEvent, callee: ƒ, Symbol(Symbol.iterator): ƒ]
      
    if (timerID) clearTimeout(timerID); // 调用一次 就清除上一次的定时器
      
    // 如果第一次需要立即执行
    if (immediate) {
      const callNow = !timerID;  // 当第一次触发事件时,timerID为null,则callNow为true
      timerID = setTimeout(() => {
        timerID = null; // 相当于清空定时器
      }, wait);
      // 没有定时器id,则执行函数
      if (callNow) {
        fn.apply(context, args);
      }
    }
      
    // 第一次不需要立即执行 有定时器id,则防抖延迟
    else {
      timerID = setTimeout(() => {
        fn.apply(context, args);
      }, wait);
    }
  };
}

使用:

const box = document.querySelector('.box');

// 要执行的函数
const doSomeThing = function (e) {
  // console.log(this);
  // console.log(e); // e是[MouseEvent]事件对象
  // 要执行的事情:比如发送ajax请求···
  console.log('啦啦');
};

box.onmousemove = debounce(doSomeThing, 500, true);

节流

节流就是限制一个函数在一段时间内只能执行一次,过了这段时间,在下一段时间又可以执行一次。

连续触发事件,但是在 n 秒中只执行一次函数。 节流会稀释函数的执行频率。

应用场景:

  1. 输入框的联想,可以限定用户在输入时,只在每两秒钟响应一次联想。
  2. 搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。
  3. 表单验证
  4. 按钮提交事件
<input type="text" id="input">

封装节流函数:

function throttle(fn, wait) {
  let timerID = null;
  let prev = new Date().getTime();  // 上一次触发的时间戳
    
  // 返回闭包函数
  return function () {
    const context = this; // 保存this
    // console.log(this); // this是触发事件对象<input type="text" id="input">
    const args = [...arguments]; // 保存事件参数
    // console.log(arguments); // Arguments [KeyboardEvent, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    let now = new Date().getTime(); // 现在触发的时间戳

    // 清除定时器
    clearTimeout(timerID);

    // 如果两次间隔时间>设定的等待时间,则执行事件处理函数fn,并且把这次调用的时间设置为上一次执行时间
    if (now - prev >= wait) {
      fn.apply(context, args);
      prev = new Date().getTime();
    } else {
      // 否则,过了剩余时间,执行最后一次fn
      timerID = setTimeout(() => {
        fn.apply(context, args);
      }, wait);
    }
  };
}

使用:

const input = document.querySelector('#input');

function check() {
  let val = this.value;
  if (val.length < 6) {
    console.log('长度不够');
  } else {
    console.log('验证通过');
  }
};

input.onkeyup = throttle(check, 1000);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值