前端学习日记 - 前端函数防抖详解

前端学习日记 - 前端函数防抖详解

前端函数防抖详解

在现代 Web 应用中,函数防抖(debounce)是一种常见且高效的性能优化手段,用于限制高频事件触发下的函数调用次数,从而减少不必要的计算、网络请求或 DOM 操作。本文将从“为什么使用防抖”切入,介绍典型的应用场景,深入解析防抖原理,并给出从零实现到在实际项目中使用 Lodash 的完整代码示例,帮助你快速掌握前端防抖技术。

在这里插入图片描述

为什么使用防抖

函数防抖的核心思想是在连续触发的事件停止后,仅执行最后一次调用,以避免频繁触发带来的性能问题 ([MDN Web Docs][1])。
在不使用防抖的情况下,例如在 input 输入事件或 window.resize 事件中直接调用逻辑,页面可能会因短时间内大量调用而出现卡顿或请求风暴 ([GeeksforGeeks][2])。
通过防抖,可以让函数在用户停止输入、滚动或调整窗口大小后的一定延迟内才执行,极大提高资源利用效率并提升用户体验 ([Medium][3])。

函数防抖的应用场景

  1. 输入框实时搜索建议
    在用户输入关键词时触发搜索接口,若不加限制,每次 keyup 都会发起请求,极易导致接口压力过大。使用防抖后,只在用户停止输入(如 300ms)后才发送请求,有效降低调用次数 ([自由代码营][4])。
  2. 按钮防连点
    对于提交表单或支付按钮,连续点击可能导致多次提交。给点击事件绑定防抖函数,可在用户短时间内多次点击时只执行一次提交操作 ([DEV Community][5])。
  3. 窗口大小调整(resize)
    当页面布局需根据窗口大小实时计算或重绘时,resize 事件会频繁触发,添加防抖能减少重绘次数,提升性能 ([Medium][6])。
  4. 滚动监听
    结合无限滚动或懒加载,当用户滚动页面时应控制数据加载频率,避免重复请求或过度渲染 ([Medium][3])。

函数防抖原理与手写实现

原理

防抖函数通过内部维护一个定时器 ID,每次调用时先清除之前的定时器,再启动一个新的延迟执行定时器;只有在最后一次调用后的延迟时间到达后,才真正执行目标函数 ([GeeksforGeeks][2], [Gist][7])。

手写实现

/** * 简易版防抖函数 * @param {Function} func - 需要防抖的函数 * @param {number} wait - 延迟时间(毫秒) * @returns {Function} - 防抖后返回的新函数 */functiondebounce(func, wait){let timeoutId;// 声明定时器 IDreturnfunction(...args){// 返回一个闭包函数clearTimeout(timeoutId);// 清除上一次定时器 timeoutId =setTimeout(()=>{// 启动新的定时器func.apply(this, args);// 延迟执行目标函数}, wait);};}

上述代码利用 JavaScript 闭包,让每个防抖函数维护独立的 timeoutId,在多次调用时只有最后一次延迟结束后触发 ([Stack Overflow][8])。

使用 Lodash 的 _.debounce

在实际项目中,为了减少手写错误并获得更丰富的功能(如 leadingtrailingcancelflush 等选项),推荐使用成熟的工具库 Lodash 的 _.debounce 方法 ([Lodash][9])。

# 安装 lodash.debounce 子模块npminstall lodash.debounce 
import debounce from'lodash.debounce';/** * 在搜索框中使用防抖 * 当用户停止输入 300ms 后才触发搜索 */const searchInput = document.getElementById('search');functiononSearch(query){// 发送搜索请求 console.log('搜索关键词:', query);}const debouncedSearch =debounce(onSearch,300,{ leading:false, trailing:true}); searchInput.addEventListener('input',(e)=>{debouncedSearch(e.target.value);});
  • leading: 是否在延迟开始前调用一次,默认 false
  • trailing: 是否在延迟结束后调用一次,默认 true
  • 返回的函数还拥有 cancel()flush() 方法,可在需要时取消或立即执行待定调用 ([GeeksforGeeks][10])。

完整示例:防抖搜索组件

下面给出一个完整的示例,包括 HTML、样式与 JavaScript 代码,你可以直接复制运行:

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>Debounce Demo</title><style>body{font-family: sans-serif;padding: 2rem;}#results{margin-top: 1rem;}.item{padding: 0.5rem 0;border-bottom: 1px solid #eee;}</style></head><body><h1>Debounce 搜索示例</h1><inputid="search"type="text"placeholder="输入关键词…"autocomplete="off"/><divid="results"></div><scripttype="module">import debounce from'lodash.debounce';const search = document.getElementById('search');const results = document.getElementById('results');// 模拟异步搜索函数asyncfunctionfetchResults(query){// 假数据return['苹果','香蕉','橘子','西瓜'].filter(item=> item.includes(query));}asyncfunctionhandleSearch(query){const list =awaitfetchResults(query); results.innerHTML = list.map(item=>`<div>${item}</div>`).join('');}// 300ms 防抖,禁止 leading,允许 trailingconst debouncedHandle =debounce(handleSearch,300,{ leading:false}); search.addEventListener('input',e=>{const q = e.target.value.trim();if(q)debouncedHandle(q);else results.innerHTML ='';});</script></body></html>

结语

函数防抖是前端性能优化中的一项基础技术,适用于各种需要限制高频事件调用的场景,通过简单的定时器逻辑或成熟的 Lodash 工具库,就能快速落地。掌握防抖和其“兄弟”节流(throttle),能让你的应用在面对频繁用户交互时依然保持流畅、稳定。欢迎在项目中实践并根据业务需求调整参数,实现更灵活的性能优化。

Read more

唤醒80年代记忆:基于百度地图的一次老式天气预报的WebGIS构建之旅

唤醒80年代记忆:基于百度地图的一次老式天气预报的WebGIS构建之旅

目录 一、省会城市信息构建 1、省会城市空间查询 2、Java后台查询 二、Java省会城市天气查询 1、与百度开放平台集成天气 2、响应对象属性介绍 3、省会天气实况展示 三、WebGIS应用构建 1、背景音乐集成 2、城市标记及天气展示 3、城市轮播 4、成果展示 四、总结 前言         在数字技术飞速发展的今天,我们常常沉浸于各种高科技带来的便捷与震撼之中,却容易忽视那些曾经陪伴我们成长、承载着时代记忆的旧事物。80年代的天气预报,便是这样一份珍贵的文化遗产。它以简洁而质朴的方式,传递着天气信息,也传递着那个时代的气息。那种对自然的敬畏、对信息的渴望,以及一家人共同分享的温馨氛围,都深深烙印在我们的记忆中。然而,随着时间的推移,天气预报的形式已经发生了翻天覆地的变化。高清的画面、精准的数据、个性化的推送……这些现代技术带来的便利固然令人欣喜,但也在一定程度上让我们失去了那份对天气预报本身的纯粹情感。于是,

By Ne0inhk
Windows下载、安装并运行MinIO,访问WebUI界面

Windows下载、安装并运行MinIO,访问WebUI界面

MinIO MinIO 是一款基于 Apache License v2.0 开源协议的对象存储服务,兼容 Amazon S3 云存储服务接口,可用于存储海量非结构化数据(如图片、视频、日志文件等)。本教程针对 Windows 系统搭建本地 MinIO 服务,适合开发测试、小型项目部署场景。 下载MinIO 官网下载 访问MinIO中文官网或MinIO英文官网,根据读者的操作系统选择相应的操作系统版本点击MinIO Server/AIStor Server和MinIO Client/AIStor Client的Download按钮下载对应文件。 说明:两版官网域名不同,Server/Client 的文字标题有差异,但下载文件一致;中文官网下载速度更快,优先推荐。 网盘下载 通过网盘分享的文件:Minio 链接: https://pan.baidu.com/s/

By Ne0inhk
【初阶数据结构和算法】八大排序算法之插入排序(直接插入排序、希尔排序及其对比)

【初阶数据结构和算法】八大排序算法之插入排序(直接插入排序、希尔排序及其对比)

文章目录 * 一、常见排序算法分类 * 一、直接插入排序 * 二、希尔排序 * 三、直接插入排序和希尔排序性能对比 一、常见排序算法分类 常见的排序算法有八种,我们简单盘点一下 1. 插入排序:直接插入排序、希尔排序 2. 选择排序:直接选择排序、堆排序 3. 交换排序:冒泡排序、快排 4. 希尔排序 5. 计数排序 以上就是我们常用的八大排序算法,我们会在后面的排序算法部分为大家一一介绍,今天我们要介绍的就是插入排序这一大类排序(更新) 一、直接插入排序 我们先来简单地介绍一下直接插入排序的思想: 直接插⼊排序是⼀种简单的插⼊排序法,其基本思想是:把待排序的记录按其关键码值的⼤小逐个插⼊到⼀个已经排好序的有序序列中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列,我们举一个简单的例子,

By Ne0inhk

OCR识别效果对比:CRNN与传统算法的视觉差异

OCR识别效果对比:CRNN与传统算法的视觉差异 📖 技术背景:OCR文字识别的核心挑战 光学字符识别(Optical Character Recognition, OCR)是将图像中的文字内容转化为可编辑文本的关键技术,广泛应用于文档数字化、票据处理、车牌识别、智能办公等场景。尽管OCR技术已有数十年发展历史,但在复杂背景、低分辨率、手写体、倾斜排版等现实条件下,识别准确率仍面临巨大挑战。 传统OCR系统通常采用“图像预处理 → 字符分割 → 特征提取 → 分类识别”的流水线式架构。这类方法依赖大量人工设计的规则和几何特征(如边缘检测、投影分析),在理想环境下表现尚可,但面对真实世界中光照不均、字体多样、背景干扰等问题时,鲁棒性显著下降。 随着深度学习的发展,端到端的神经网络模型逐渐取代传统流程,其中 CRNN(Convolutional Recurrent Neural Network) 成为工业界主流的通用OCR解决方案。它通过卷积层提取空间特征、循环层建模序列依赖、CTC(Connectionist Temporal Classification)损失函数实现对齐,

By Ne0inhk