码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-06-15 16:05:07      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:func   round   ons   timeout   后台   就是   nts   日常   body   

 什么是防抖?

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

为什么要进行防抖?

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

常见的需要防抖的场景: 搜索框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>
技术图片

点击一下按钮就可以啦。

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

标签:func   round   ons   timeout   后台   就是   nts   日常   body   

原文地址:https://www.cnblogs.com/weijiangZ/p/13131108.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!