• 如何实现防抖、节流?


    1. 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效;
    2. 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

    1、防抖

    应用场景:

    1. scroll事件滚动触发
    2. 搜索框输入查询
    3. 表单验证
    4. 按钮提交事件
    5. 浏览器窗口缩放
    6. resize事件

    正常情况:快速点击按钮,无论你点的有多快,只要点了一次,日志就会打印一次?

    需求:在快速点击的过程中,如何只让最后一次能产生效果?

    示例代码:

    核心:

    1. 运用到定时器setTimeout()
    2. 每次点击需要清除上一次点击产生的定时器,保证最后一次点击产生的定时器才是有效可用的
    <body>
    <button class="button">点击</button>
    
    <script type="text/javascript">
        <!--    防抖:用户点击=》多次点击会多次发送请求=》浪费性能-->
        //1、添加点击事件
        //2、添加防抖:1、定时器,2、高阶函数
        const button = document.querySelector('button');
    
        //防抖:在规定的时间点击一次
        button.addEventListener('click', debounce(change, 2000))
    
        //高阶函数:1、函数的返回值是一个函数或者参数是一个函数
        function debounce(fn, time=250) {
            let timer = null;//1、这个变量会保存在内存中,只会创建一次
            //用到定时器,规定的时间内只执行一次
            return function (e) {
                console.log("this", this);
                //判断定时器是否生成,如果生成了,清除上一次点击的定时器,保证只有最后一次点击的定时器才有用
                if (timer) {
                    clearTimeout(timer);
                }
    
                let firstClick = !timer;
                //如果是第一次点击就立即执行
                if (firstClick) {
                    //拿到外部函数的this,即按钮这个节点,将fn()函数的this指向
                    fn.apply(this, arguments);//处理业务逻辑
                }
                timer = setTimeout(() => {
                    timer = null;
                }, time)
            }
        }
    
        function change(e) {
            console.log(e);
        }
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    2、节流

    应用场景:

    1. scroll:每隔一段时间计算位置信息
    2. 搜索框:实时搜索并发送请求,展示下拉列表

    需求:如果你持续触发事件,每隔一段时间,只会执行一次事件

    实现的两种方式:

    1、定时器

    核心:

    1. 运用到定时器setTimeout()
    2. 需要一个控制是否能够发送请求的阀门(节流阀)
    <body>
    <button class="button">点击</button>
    
    <script type="text/javascript">
      	const button = document.querySelector('button');
        button.addEventListener('click', throttle(change, 2000));
    
        function change() {
            console.log("发送请求了...");
        }
    
        function throttle(fn, time=250) {
        
            /*注意这里用到了闭包*/
            let flag = true;//设置节流阀;这个变量会保存在内存中,只会创建一次
            return () => {
                if (flag) {
                    flag = false;//flag值变为false
                    //发起请求
                    fn();
                    //通过定时器,2s后将flag的值变为true,点击按钮才可再次发送请求
                    setTimeout(() => {
                        flag = true
                    }, time)
                }
            }
        }
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2、时间戳

    核心:

    • 获取触发事件时的时间戳,判断当前时间戳与初始时间戳是否大于执行间隔时间
    <body>
    <button class="button">点击</button>
    
    <script type="text/javascript">
        const button = document.querySelector('button');
        button.addEventListener('click', throttle(change, 2000));
    
        function change() {
            console.log("发送请求了...");
        }
    
        function throttle(fn, time=250) {
        	/*注意这里用到了闭包*/
            let begin = 0;//设置时间戳
            return () => {
                //获取当前时间戳
                let date = new Date().getTime();
                //判断当前的时间戳与上一次点击的时间戳的差是否大于time
                if (date - begin > time) {
                    fn();
                    begin = date;
                }
            }
        }
    </script>
    </body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    webstorm 中使用 Eslint+Prettier统一代码风格
    ETCD快速入门-01 ETCD概述
    调整视频帧率、分辨率
    Spring 源码(8)Spring BeanPostProcessor的注册、国际化及事件发布机制
    【Java-----异常处理机制详解】
    图扑智慧电力可视化大屏,赋能虚拟电厂精准减碳
    腾讯云新用户什么云服务器值得买?
    Excel 多条件筛选 与 数据透视表 实现
    多链路自检与灵活组网:新能源充电桩物联网5G工业路由器
    Frustum PointNets for 3D Object Detection from RGB-D Data(2018)
  • 原文地址:https://blog.csdn.net/fangqi20170515/article/details/126265081