JavaScript高级:防抖和节流

本文介绍了防抖(debounce)和节流(throttle)两种IT技术,用于解决单位时间内频繁触发事件导致的性能问题,通过示例和代码展示了如何使用lodash库和自定义函数实现这两种机制,以及在视频播放场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 防抖(debounce)

单位时间内,频繁触发事件,只执行最后一次

【例子】王者荣耀英雄回城,只要被打断就要重新来

【应用场景】1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;2. 手机号、邮箱验证输入检测。

【需求】鼠标在盒子上滑动,并在盒子上显示滑动的次数

如果不使用防抖, 那么在盒子上的数字将会增加的非常快,如果是一些非常消耗性能的代码,可能会造成卡顿

1.1 使用 lodash 库实现防抖

无论滑动多少下 1s后才加1

       语法:

        _.debounce(func, [wait=0], [options={}])

        func: 需要防抖的函数

        wait: 延迟执行的时间

        options: 配置对象

【代码】

const box = document.querySelector('.box')
let i = 1
function mouseMove() {
    // 如果里面存在大量消耗性能的代码,比如dom操作,比如数据处理,可能造成卡顿
    box.innerHTML = i++
}
box.addEventListener('mousemove', _.debounce(mouseMove, 1000))

1.2 手写防抖函数

【代码】

        // 2.手写防抖函数
        // 核心是利用 setTimeOut 定时器实现
        // 2.1 声明定时器变量
        // 2.2 每次鼠标移动(事件触发)的时候先判断是否有定时器,如果有则清除以前的定时器
        // 2.3 如果没有定时器,则开启定时器,存入定时器变量里面
        // 2.4 在定时器里面写函数调用


        function debounce(fn, t) {
            let timer = null
            return function () {
                if (timer) clearTimeout(timer)
                timer = setTimeout(function () {
                    fn()
                }, t)
            }
        }

        box.addEventListener('mousemove', debounce(mouseMove, 500))

2 节流(throttle)

 单位时间内,频繁触发事件,只执行一次

【例子】王者荣耀英雄技能,在那段时间内你只能用一次该技能,下次想要用,需要等待技能冷却完毕

【应用场景】1. 鼠标连续触发某事件(如鼠标连续点击),只在单位时间内执行一次; 2. 监听滚动事件scroll,每隔100ms执行一次,实现防抖效果;3.页面尺寸缩放 resize

2.1 使用lodash库实现节流

        语法:

        _.throttle(func, [wait=0], [options={}])

        func: 需要节流的事件处理函数

        wait: 在wait 秒内最多执行func 一次的函数

box.addEventListener('mousemove', _.throttle(mouseMove, 3000))

2.2 手写节流函数

        // 2.2 手写节流函数
        // 核心是利用 setTimeOut 定时器实现
        // 2.2.1 声明定时器变量
        // 2.2.2 每次鼠标移动(事件触发)的时候先判断是否有定时器,如果有则清除以前的定时器
        // 2.2.3 如果没有定时器,则开启定时器,存入定时器变量里面
        // 2.2.4 在定时器里面写函数调用
        function throttle(fn, t) {
            let timer = null
            return function () {
                if (timer) return
                timer = setTimeout(function () {
                    fn()
                    timer = null
                }, t)
            }
        }
        box.addEventListener('mousemove', throttle(mouseMove, 3000))

因为在 setTimeout 中是无法删除定时器的,因为定时器还在运作,所以使用timer = null 

3 节流案例

【需求】在一个网页中播放了一个视频,在我下次再次打开这个页面时,视频的进度在我之前播放到的位置

【补充知识】

【代码】 

  <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
  <script>
    // ontimeupdate  触发频次太高,我们设定 1秒钟触发一次
    const video = document.querySelector('.video video')
    video.ontimeupdate = _.throttle(() => {
      // console.log(video.currentTime)
      // 把间隔一秒就把当前播放时间存储到本地存储中
      localStorage.setItem('currentTime', video.currentTime)
    }, 1000)


    // 打开页面的时候,从本地存储中获取当前播放时间
    video.onloadeddata = () => {
      video.currentTime = localStorage.getItem('currentTime') || 0
    }


  </script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小蟹呀^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值