聊一聊前端 JS 的防抖和节流

前言

任务

  如上图这是今天老师布置的一个任务,当初次看到任务要求时,对所述的防抖和节流是非常的陌生,第一件事就是去查阅资料了,逛了各种的教程平台,博客平台,结合了一下总结出了本篇文章,总结不易,希望可以得到大家的鼓励,当然有哪里不对的地方还请指出,感谢?

一、为什么需要使用防抖和节流

实践最容易看清一切,直接给大家示例吧,其实实际应用场景中是浏览器窗口滚动加载、搜索框输入内容,窗口大小拖拽等,为了让大家看的更加清楚,给大家举一个简单的点击按钮例子

  • 示例

    <body>
        <!-- 定义一个按钮 -->
        <button>点击按钮</button>
    
        <script>
            // 获取按钮
            var btn = document.querySelector('button')
    
            // 绑定点击事件
            btn.addEventListener('click', function () {
                // 控制台输出内容
                console.log('欢迎阅读张浔的博客')
                console.log('----------------')
            })
        </script>
    </body>
    

​  从上图可以发现,点击一次按钮触发一次事件,如果这个事件为发送一个请求,那么这对于服务器来说会加重负担,降低性能,很可能会造成页面的卡顿,导致用户体验非常糟糕,为了优化体验,我们采用 debounce (防抖)和 throttle (节流)的方式来减少触发事件的频率。

二、debounce 防抖

2.1 概念

  • 说明
    • 防抖又叫函数防抖
    • 指的是触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计时

从生活中下手,发现了一个很好的比喻分享给大家

  如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时),这样举例,你是不是理解了呢,in细品? 作者来源

2.2 实现

实现部分就给大家举例实际的应用场景:滚动加载案例

实现之前

scrollTop

在为什么需要使用防抖和节流中已经做过了解释,相信大家也都明白为什么会这样

实现之后

  • 代码
    • 防抖的关键需要 setTimeout 定时器来辅助实现,延迟运行需要执行的代码
    • 如果事件多次触发,则把定时器关掉 clearTimeout ,重新开始计时
    • 若计时期间事件没有被重新触发,等计时完毕,则运行需要执行的代码

不了解闭包概念的同学点击 闭包文章

<body>
    <div class="box">
        人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。
        人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,
        该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。
        人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,
        未来人工智能带来的科技产品,将会是人类智慧的“容器”。
        人工智能可以对人的意识、思维的信息过程的模拟。
        人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。
    </div>

    <script>
        // 获取 盒子 
        var box = document.querySelector('.box')

        // 防抖
        function debounce(fn, wait) {
            //定义一个定时器
            var timer = null      
            return function () {
                if (timer !== null) {
                    //清除这个定时器
                    clearTimeout(timer)
                }
                timer = setTimeout(fn, wait)
            }
        }

        // 滚动事件
        box.addEventListener('scroll', debounce(scTop, 1000))

        // 处理函数
        function scTop() {
            console.log(box.scrollTop)
        }
    </script>
</body>
  • 效果图

    scrollTop防抖

    如上图所见,在滚动过程中并没有持续执行,有效减少了性能的损耗

三、throttle 节流

3.1 概念

  • 说明
    • 节流又叫函数节流
    • 指的是当持续触发事件时,每隔一定的时间,只执行一次函数,我自己理解为匀速执行

生活中,我自己构想的了一个例子来比喻节流

  大家玩游戏时,一般右上角会有个几个值,其中 60FPS,这个 FPS 是帧数的意思,数字 60 代表的是每秒连续播放60帧(1帧表示1张)以上的图片,那在人们眼的视觉中就会形成一个连贯的动画,一般的游戏 60 帧就够了,当帧数越高时,是非常的吃电脑的性能(散热器在狂转?),这样就会很浪费资源,当然,我们排除家里有矿电脑配置很666的?

  那为了给服务器减轻负担,这时我们就会使用节流来限制触发事件时执行的函数次数。

3.2 实现

继续接着上一次案例实现吧

  • 代码

    <script>
        // 获取 盒子 
        var box = document.querySelector('.box')
    
        // 节流
        function throttle(func, delay) {
            // 定义计时器
            var timer = null
            return function () {
                var args = arguments
                if (!timer) {
                    timer = setTimeout(function () {
                        func.apply(this, args)
                        timer = null
                    }, delay)
                }
            }
        }
    
        // 滚动事件
        box.addEventListener('scroll', throttle(scTop, 1000))
    
        // 处理函数
        function scTop() {
            console.log(box.scrollTop)
        }
    </script>
    
  • 效果图
    在这里插入图片描述
    如上图所见,在滚动过程中并没有持续执行,而是每隔 1秒 输出一次,这就是节流

总结

防抖和节流相同点:

  • 都可以通过 setTimeout 实现
  • 都是降低执行频率,节省计算资源

防抖和节流不同点:

  • debounce 防抖是在一段连续操作结束后,执行函数,利用 setTimeoutclearTimeout 实现,throttle 节流是在一段连续操作中,每隔一段时间只执行一次,频率较高的事件中使用,用来提高性能。
  • debounce 防抖关注一定时间连续触发的事件,只在最后执行一次,而 throttle 节流一段时间内只执行一次

逛着玩时发现一个可视化的 demo,比较更形象的演示和理解 作者来源

应用场景

debounce 防抖:

  • 搜索框搜索输入,只需用户最后一次输入完再发送请求
  • 手机号、邮箱验证输入检测
  • 窗口大小 resize,只需窗口调整完成后,计算窗口大小,防止重复渲染

throttle 节流:

  • 滚动加载,加载更多或滚到底部监听
  • 搜索框,搜索联想功能

在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>