zoukankan      html  css  js  c++  java
  • 前端日常开发常用功能系列之防抖

    这是前端日常开发常用功能这个系列文章的第一篇,该系列是日常开发中一些常用的功能的再总结、再提炼,以防止遗忘,便于日后复习。该系列预计包含以下内容: 防抖、节流、去重、拷贝、最值、扁平、偏函数、柯里、惰性函数、递归、乱序、排序、注入、上传、下载、截图。。。

     什么是防抖?

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

    为什么要进行防抖?

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

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

    如何做到防抖呢?

    版本1

    <html>
    <head>
    <meta charset="UTF-8">
    <style>
        div {
             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 {
             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 {
             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>

    点击一下按钮就可以啦。

    可能待完善。。。

  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/innooo/p/10430624.html
Copyright © 2011-2022 走看看