前端日常开发常用功能系列之防抖

Posted weijiangz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端日常开发常用功能系列之防抖相关的知识,希望对你有一定的参考价值。

 什么是防抖?

防抖就是对于频繁触发的事件添加一个延时同时设定一个最小触发间隔,如果触发间隔小于设定的间隔,则清除原来的定时,重新设定新的定时;如果触发间隔大于设定间隔,则保留原来的定时,并设置新的定时;防抖的结果就是频繁的触发转变为触发一次

为什么要进行防抖?

在频繁触发事件的场景,有些情况可能执行的逻辑比较复杂或者耗时,此时浏览器的处理跟不上触发,就会发生卡顿、假死或者事件堆积,这里防抖就可以一定程度上解决或者缓解这种故障。

常见的需要防抖的场景: 搜索框keyup、keydown等触发后台请求; 频繁改变窗口大小resize;鼠标移动mousemove事件;类似以上频繁触发并且处理逻辑较为耗时或者触发时需要请求后台接口;

如何做到防抖呢?

版本1

技术图片
<html>
<head>
<meta charset="UTF-8">
<style>
    div {
        width: 500px;
        height: 300px;
        background: orange;
    }
</style>
</head>
<body>
    <div id="div"></div>
</body>
<script>
    const div = document.getElementById(‘div‘);


    const debounce = (fn, wait) => {
        let timer;

        return function() {
            clearTimeout(timer);
            timer = setTimeout(() => {
                fn.apply(this, arguments);
            }, wait);
        }
    };

    const fn = debounce((e) => {
        console.log(‘move‘, e);
    }, 1000)

    div.addEventListener(‘mousemove‘, fn);
</script>
</html>
技术图片

执行结果: 在橙色区域移动鼠标,只在停止移动后才会触发一次事件;

如果我们想让事件立即触发一次呢?

版本2

技术图片
<html>
<head>
<meta charset="UTF-8">
<style>
    div {
        width: 500px;
        height: 300px;
        background: orange;
    }
</style>
</head>
<body>
    <div id="div"></div>
</body>
<script>
    const div = document.getElementById(‘div‘);


    const debounce = (fn, wait, immediate = false) => {
        let timer;

        return function() {
            if(timer) clearTimeout(timer);
            if(immediate) {
                let trigger = !timer;
                timer = setTimeout(() => {
                    timer = null;
                }, wait);

                if(trigger) {
                    fn.apply(this, arguments);
                }
                return;
            }

            timer = setTimeout(() => {
                fn.apply(this, arguments);
            }, wait);
            return;
        }
    };

    const fn = debounce((e) => {
        console.log(‘move‘, e);
    }, 1000, true)

    div.addEventListener(‘mousemove‘, fn);
</script>
</html>
技术图片

执行结果是: 立即触发一次,然后停止触发1s后才能再次触发

如果这个防抖时间比较长,比如是5s,我希望可以取消这种“挂起”状态

技术图片
<html>
<head>
<meta charset="UTF-8">
<style>
    div {
        width: 500px;
        height: 300px;
        background: orange;
    }
</style>
</head>
<body>
    <div id="div"></div>
    <button id="btn">取消debounce</button>
</body>
<script>
    const div = document.getElementById(‘div‘);
    const btn = document.getElementById(‘btn‘);

    const debounce = (fn, wait, immediate = false) => {
        let timer;
        const debounced =function(){
            if(timer) clearTimeout(timer);
            if(immediate) {
                let trigger = !timer;
                timer = setTimeout(() => {
                    timer = null;
                }, wait);

                if(trigger) {
                    fn.apply(this, arguments);
                }
                return;
            }

            timer = setTimeout(() => {
                fn.apply(this, arguments);
            }, wait);
            return;
        }
        
        debounced.cancel = () => {
            clearTimeout(timer);
            timer = null;
        }
        return debounced;
    };

    const fn = debounce((e) => {
        console.log(‘move‘, e);
    }, 2000, true)

    div.addEventListener(‘mousemove‘, fn);
    btn.addEventListener(‘click‘, fn.cancel)
</script>
</html>
技术图片

点击一下按钮就可以啦。

以上是关于前端日常开发常用功能系列之防抖的主要内容,如果未能解决你的问题,请参考以下文章

前端日常开发常用功能系列之数组去重

跟着大佬学JavaScript之防抖

「PHP开发APP接口实战009」日常安全防范之防SQL入和XSS攻击

译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务

前端开发常用代码片段(中篇)

前端开发常用js代码片段