3分钟学会防抖和截流及使用场景、代码段

1,469 阅读2分钟

前言

首先明白一点,防抖和截流都是用于 高频异步 触发场景,目的都是为了让事件只触发一次。例如按钮不停的提交表单(异步操作),滚动条的上拉加载数据(异步操作),输入框的搜索联想(异步操作)等。区分防抖和截流在于高频点击 第一次 触发事件后,是否立马执行和 再次 触发事件后的反应。 记住第一次事件就生效,还是延迟生效,就能理顺防抖和截流的区别了。

防抖(debounce)

事件被触发延迟n秒后执行,如果在这n秒内又被触发,则重新计时。 个人理解:最后一次事件经过n秒后执行。

从防抖的定义来考虑代码怎么写:

  1. 延迟n秒后执行(有定时器)
  2. n秒内触发,重新计时(第二次触发事件的时候,定时器会被清空)
function debounce(fn, delay) {
    let timer; // 定时器对象
    return function(...args) {
        // 2. 如果定时器对象存在,则清除重新计时
        timer && clearTimeout(timer);
        // 1. 主逻辑,延迟n秒后执行
        timer = setTimeout(()=> {
            fn.apply(this, args); //  Todo:执行你的函数
            timer = null;
        },delay);
    }

}

截流(throttle)

事件被触发后立即执行,如果在这n秒内又被触发,则不会生效。个人理解:第一次事件执行后,n秒后才能再执行。

从截流的定义来考虑代码怎么写:

  1. 触发事件后,立即执行
  2. n秒内触发,不生效(现在的时间跟之前时间比,是否经过n秒,经过n秒触发才生效)
function throttle(fn, delay) {
    // 需要3个时间:当前时间 now、延迟时间 delay、最后时间 last
    let last = 0;
    return function(...args) {
        const now = +new Date(); // 获得当前时间
        // 1. 触发事件后,立即执行函数,第一次 now - last 永远大于 延迟时间
        // 2. 前后两次事件时间对比,是否过了设定的延迟时间。
        if(now - last > delay) {
            last = now;
            fn.apply(this, args); // Todo:执行你的函数
        }
    }
}

应用场景

防抖

  • 搜索,输入联想
  • window触发 resize时间,窗口大小改变

截流

  • 表单提交,按钮点击
  • 滚动上拉加载