JS防抖和节流,手写实现

一、什么是防抖和节流?

函数防抖和节流,都是控制事件触发频率的方法。

防抖:假设函数持续多次执行,我们希望让它冷静下来再执行。也就是当持续触发事件的时候,函数是完全不执行的,等最后一次触发结束的一段时间之后,再去执行。

节流:让函数有节制地执行,而不是毫无节制的触发一次就执行一次。
什么叫有节制呢?就是在一段时间内,只执行一次。
节流顾名思义则是将减少一段时间内触发的频率,指定时间间隔内只会执行一次任务。

防抖场景

  • 文本输入的验证,连续输入文字后发送 AJAX 请求进行验证,验证一次就好。
    • 监听一个输入框的,文字变化后触发change 事件
    • 直接用keyup 事件,则会频发触发change事件
    • 防抖:用户输入结束或暂停时,才会触发change事件
  • 用户快速点击翻页时,只需要执行用户最后一次希望到达的页数即可,中间页数都是用户不希望看到的,使用防抖函数可以有效的减少发送请求的次数

节流场景

  • 懒加载要监听计算滚动条的位置,使用节流按一定时间的频率获取

  • DOM 元素的拖拽功能实现(mousemove)

    • 拖拽一个元素时,要随时拿到该元素被拖拽的位置
    • 直接用drag事件,则会频繁触发,很容易导致卡顿
    • 节流:无论拖拽速度多快,都会每隔100ms触发一次

二、初步实现

防抖

const input = document.querySelector('#input');
let timer = null;
input.addEventListener('keyup', function () {
    
    
  clearTimeout(timer);
  timer = setTimeout(() => {
    
    
    // 模拟触发change事件
    console.log(input.value);
  }, 500);
});

节流

const div1 = document.getElementById('div1');

let timer = null;

div1.addEventListener('drag', e => {
    
    
  if (timer) {
    
    
    return;
  }
  timer = setTimeout(() => {
    
    
    console.log(e.offsetX, e.offsetY);
    timer = null;
  }, 100);
});

三、函数封装

防抖封装

function debounce(fn, delay = 500) {
    
    
  // timer 是在闭包中的
  let timer = null;
  return function () {
    
    
    clearTimeout(timer);
    timer = setTimeout(() => {
    
    
      fn.apply(this, arguments);
    }, delay);
  };
}

input.addEventListener(
  'keyup',
  debounce(function () {
    
    
    console.log(input.value);
  })
);

节流封装

div1.addEventListener(
  'drag',
  throttle(function (e) {
    
    
    console.log(e.offsetX, e.offsetY);
  })
);

function throttle(fn, delay = 100) {
    
    
  let timer = null;
  return function (e) {
    
    
    if (timer) {
    
    
      return;
    }
    timer = setTimeout(() => {
    
    
      fn.apply(this, arguments);
      // fn(e)
      timer = null;
    }, delay);
  };
}

猜你喜欢

转载自blog.csdn.net/weixin_43792004/article/details/112547968
今日推荐