关于防抖和节流

防抖和节流

作用

  • 这两个名词是两种解决方案的称呼,为了解决频繁触发某一个函数时,限制它的调用次数,让它不要那么频繁的被调用。

为啥要这么做

  • 首先呢,在浏览器中,有2个概念,一个叫重绘,一个叫**回流**。这两个现象,是在浏览器渲染页面的时候会发生的,当页面的布局不改变,仅仅是字体大小颜色等改变时就会发生重绘;当页面布局发生改变(比如width、height、margin、padding等),会发生回流。
  • 上述的这两个现象挺影响性能的,所以当我们的操作会导致发生这两个现象时,一般就可以使用防抖和节流来,尽可能的减少这样的操作,不至于让我们的程序挂掉。当然不止这样情况下才能用哈,比如触发ajax请求的时候其实也可以用,根据需要来判断。

使用

防抖

  • 原理:通过定时器来限制我们的操作只能在一个限制的时间后才能执行,当在这个限制时间内再次触发这一操作,重新开始计时,时间到后,在执行操作。
  • 举例:根据显示器窗口的宽来实时的设置合适的高,让背景图可以以最完美的比例,完全显示。(具体实现看这里),这里对window的resize事件,进行防抖的操作
    // 保存定时器
    let timeout = null;
    /**
        des:防抖函数
        @params:{fun:要调用的函数}
        @params:{wait:设置定时器延迟执行的时间}
    */  
    let debounce = function (fun,wait) {
        // 清除上次保存的定时器
        clearTimeout(timeout);
        // 创建新定时器 并保存
        timeout = setTimeout(() => {
            // 执行要操作的函数
            fun();
        }, wait);
    }
    // 监听窗口变化事件
    window.addEventListener('resize', () => {
        debounce(changeH,1000);
    });

节流

  • 原理:持续触发某一个函数(事件)的时候,每隔一段时间只执行一次;
  • 实现:有两种方式,一种是通过时间戳一种是通过设置定时器。
  • 时间戳版本:触发事件前记录一个时间,当触发事件时再记录当前时间,然后让2个时间做差在和我们设置的事件周期比较,如果大,执行事件并更新时间;小于,不执行。
    // 节流函数---时间戳版本
    // 设置初始化时间
    let initDate = Date.now();
    /**
        des:防抖函数
        @params:{fun:要调用的函数}
        @params:{wait:设置定时器延迟执行的时间}
    */ 
    let throttleOne = function (fun, wait) {
        // 获取当前时间
        let currentDate = Date.now();
        // 当执行函数的时间戳和第一次的时间戳做差大于设置的周期时,才执行函数,并更新时间戳
        if (currentDate - initDate > wait) {
            fun();
            // 更新初始化的时间为当前时间
            initDate = currentDate;
        } else {
            console.log('没执行');
        }
    }
    // 监听窗口变化事件
    window.addEventListener('resize', () => {
        throttleByTimeStamp(changeH, 1000);
    });
  • 设置定时器版本:设置一个变量用来保存定时器,然后每次每次触发事件前,判断改变量是否有定时器,没有正常执行,执行后清楚触发器;如果有触发器,则不进行操作,等待上次的触发器执行完毕。
  • 特点:这个形式就是,第一次操作一定会触发事件的执行。
     // 节流函数---定时器版本
    // 用来保存定时器
    let timer = null;
    let throttleTwo = function (fun, wait) {
        // 定时器存在不执行函数,不存在就执行函数
        if (timer == null) {
            timer = setTimeout(
                () => {
                    fun();
                    timer=null;
                }, wait
            );
        }else{
            console.log('没有执行');
        }
    }
    // 监听窗口变化事件
    window.addEventListener('resize', () => {
        throttleTwo(changeH, 1000);
    });

总结

2者的不同

防抖是在一段时间后,一定会执行一次
节流是在一段时间内,一定会执行一次

使用场景

这两种操作要达到的目的是一样的,但是因为特点不同,所以使用场景有时候也会有一点不同;
防抖

  • 比如我们这个例子,用防抖比较好,因为当窗口一直在变化,最后还是会停止,一但停止,就必须要保证容器大小一定要按背景图比例调整好,显示完美的效果给用户。

节流

  • 当我们的页面在无线加载的场景下,需要用户在滑动滚动条的时候,来不断的请求ajax,所以用节流就比较好。

学习参考链接

冴羽-重学JS之防抖节流
JS的防抖与节流


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!