防抖和节流

162 阅读3分钟

防抖与节流

高频率触发的业务需要减少事件处理函数的回调执行,提高浏览器性能,就有了防抖和节流的设计思想。

防抖

防抖:固定的时间段内连续多次触发事件,只执行最后一次触发事件的事件处理回调函数。

原理:维护一个计时器,规定在固定的时间段后触发事件,但是在固定的时间段内再次触发事件,就将之前的计时器清零clear计时器,只有在达到了固定时间段却没有触发事件计时器就回调计时器中的事件处理函数。这样就达到了只有最后一次事件触发的时候执行了事件处理函数。

防抖场景

1.登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖

2.调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖

3.文本编辑器实时保存,当无任何更改操作一秒后进行保存

防抖函数的封装

    <script>
        //防抖函数的封装
        //callback:是事件处理函数,在事件触发一次就执行fangdou函数,然后fangdou函数就会回调一次事件处理函数
        //delay:延迟时间,就是规定固定的时间段
        function fangdou(){
            let timer=null;
            return function(callback,delay){
                //防抖的思想:return这个函数就是要触发的点击事件其调用频率很高,利用计时器让callback这个事件处理函数只在最后一次事件触发时执行
                if(timer){
                    //计时器存在就清零计时器
                    clearTimeout(timer);
                };
                //清除计时器后不存在计时器创建新的计时器重新计时
                //在事件触发一次就会延迟delay设置的固定时间段后才执行事件处理函数
                //如果没有达到delay时间段又触发了事件,就不会执行事件处理函数
                //而是会再次执行return这个函数此时计时器存在就会清零了之前的计时器再创建一个新的计时器重新计时
                //直到最后到达了delay时间没有再次触发事件就执行了事件处理函数然后清除计时器
                timer=setTimeout(()=>{
                    callback.apply(this,arguments);//把this和参数传递过去
                    timer=null;//事件处理函数完后即业务执行完毕后把计时器清除
                },delay);
            };
        };
   </script>     

fangdou返回的闭包函数是真正的触发事件时会执行的事件函数,而闭包中的回调函数callback是事件处理函数,本来this是window,所以用this的劫持让用于做业务的回调函数callback也就是事件处理函数的this指向闭包函数也就是真正的触发事件时会执行的事件函数。回调函数callback是写在箭头函数中的,而箭头函数的this就是外层作用域也就是闭包函数this就指向了闭包函数,apply方法第1个参数就是指定调用apply方法的这个callback回调函数的this对象,箭头函数没有arguments会取外层作用域也就是闭包函数的实参集合,第2个参数可以传数组接收闭包函数的实参集合。

节流

节流:固定的时间段内连续多次触发事件,只在固定的时间段内执行一次触发事件的事件处理回调函数。

原理:维护一个计时器,通过判断是否达到固定的时间段来触发事件回调事件处理函数,没有达到固定的时间段再次触发事件函数就清除计时器把计时器引用的变量置空然后只要计时器不存在就结束触发事件函数的运行,只有到达了固定的时间段让计时器回调事件处理函数。这样就实现了只在固定的时间段内执行一次触发事件的事件处理回调函数。

节流场景

1.scroll 事件,每隔一秒计算一次位置信息等

2.浏览器播放事件,每个一秒计算一次进度信息等

3.DOM元素的拖拽功能

4.input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖)

节流函数的封装

 <script>
//节流函数的封装
        //callback:是事件处理函数,在事件触发一次就执行jieliu函数,然后jieliu函数就会回调一次事件处理函数
        //delay:延迟时间,就是规定固定的时间段
        function jieliu(callback,delay){
            return function(){
                //防抖的思想:return这个函数就是要触发的点击事件调其用频率很高,利用计时器让callback这个事件处理函数在固定时间段只执行1次
                let timer=null;
                if(timer){
                    //存在计时器,就不执行callback这个事件处理函数,直接return结束运行要触发的事件函数
                    return;
                };
                //不存在计时器,就创建一个计时器
                //事件触发一次就会延迟delay设置的固定时间段后才执行事件处理函数
                //如果没有达到delay时间段又触发了事件,就不会执行事件处理函数
                //而是会再次执行return这个函数此时计时器存在就会直接return结束当前运行的函数
                //然后在delay时间段到达以后就执行计时器中的事件回调函数再清除计时器,此时就没有了计时器
                //没有了计时器后再触发事件又创建新的计时器,再等待delay时间后执行事件处理函数
                timer=setTimeout(()=>{
                    callback.apply(this,arguments);//把this和参数传递过去
                    timer=null;//事件处理函数完后即业务执行完毕后把计时器清除
                },delay);
            };
        };
    </script>

传入的this和实参集合同理。