当前位置: 首页 > news >正文

前端函数防抖

前端函数防抖详解
    • 为什么使用防抖
    • 函数防抖的应用场景
    • 函数防抖原理与手写实现
      • 原理
      • 手写实现
    • 使用 Lodash 的 \_.debounce
    • 完整示例:防抖搜索组件
    • 结语

在现代 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} - 防抖后返回的新函数*/
function debounce(func, wait) {let timeoutId;                                 // 声明定时器 IDreturn function(...args) {                    // 返回一个闭包函数clearTimeout(timeoutId);                     // 清除上一次定时器timeoutId = setTimeout(() => {               // 启动新的定时器func.apply(this, args);                    // 延迟执行目标函数}, wait);};
}

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

使用 Lodash 的 _.debounce

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

# 安装 lodash.debounce 子模块
npm install lodash.debounce
import debounce from 'lodash.debounce';

/**

  • 在搜索框中使用防抖
  • 当用户停止输入 300ms 后才触发搜索
    */
    const searchInput = document.getElementById(‘search’);
    function onSearch(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 代码,你可以直接复制运行:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="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><input id="search" type="text" placeholder="输入关键词…" autocomplete="off" /><div id="results"></div><script type="module">import debounce from 'lodash.debounce';
<span class="token keyword">const</span> search <span class="token operator">&#61;</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">&#39;search&#39;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> results <span class="token operator">&#61;</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">&#39;results&#39;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 模拟异步搜索函数</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetchResults</span><span class="token punctuation">(</span><span class="token parameter">query</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// 假数据</span><span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string">&#39;苹果&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;香蕉&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;橘子&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;西瓜&#39;</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">&#61;&gt;</span> item<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">handleSearch</span><span class="token punctuation">(</span><span class="token parameter">query</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">const</span> list <span class="token operator">&#61;</span> <span class="token keyword">await</span> <span class="token function">fetchResults</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">;</span>results<span class="token punctuation">.</span>innerHTML <span class="token operator">&#61;</span> list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">&#61;&gt;</span> <span class="token template-string"><span class="token template-punctuation string">&#96;</span><span class="token string">&lt;div class&#61;&#34;item&#34;&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>item<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/div&gt;</span><span class="token template-punctuation string">&#96;</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&#39;&#39;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token comment">// 300ms 防抖&#xff0c;禁止 leading&#xff0c;允许 trailing</span>
<span class="token keyword">const</span> debouncedHandle <span class="token operator">&#61;</span> <span class="token function">debounce</span><span class="token punctuation">(</span>handleSearch<span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">,</span> <span class="token punctuation">{<!-- --></span> leading<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>search<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">&#39;input&#39;</span><span class="token punctuation">,</span> <span class="token parameter">e</span> <span class="token operator">&#61;&gt;</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">const</span> q <span class="token operator">&#61;</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">if</span> <span class="token punctuation">(</span>q<span class="token punctuation">)</span> <span class="token function">debouncedHandle</span><span class="token punctuation">(</span>q<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">else</span> results<span class="token punctuation">.</span>innerHTML <span class="token operator">&#61;</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

</script>
</body>
</html>

结语

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

http://www.dtcms.com/a/344793.html

相关文章:

  • Nginx + Keepalived 实现高可用负载均衡集群
  • 前端桌面端解决方案技术选型:全面指南
  • 深入理解强化学习的target network
  • 3.5MM防水耳机插座
  • 为什么访问HTTPS站点时,会发生SSL证书错误
  • JAVA基础代码示例
  • SpringBoot -- 集成Spring Security (二)
  • LightGBM时序预测详解:从原理到 PSO 参数优化
  • 如何理解面向过程和面向对象,举例说明一下?
  • [docker/大数据]Spark快速入门
  • 【实时Linux实战系列】实时系统中的预测性维护策略
  • 能源行业合同管理难点有哪些?企业该如何应对?
  • FIFO核心原理与机制
  • QGIS 绿色版修正
  • 基于vtkImageViewer2的MPR(二):改进
  • JavaScript 操作 DOM
  • 图论——Floyd算法
  • 四十一、【高级特性篇】API 文档驱动:OpenAPI/Swagger 一键导入测试用例
  • 上市公司能源消耗数据库
  • 【python】os.makedirs和with open
  • 密码管理中硬编码密码
  • (论文速读)并行自回归视觉生成
  • 硬件驱动---linux内核驱动 启动
  • 【LeetCode】21. 合并两个有序链表
  • 开发二手车小程序时,如何确保信息的真实性和可靠性?
  • Prometheus+Grafana监控redis
  • 【连接器专题】连接器接触界面的理解
  • Elasticsearch Rails 集成(elasticsearch-model / ActiveRecord)
  • 高速互联技术——NVLink
  • SpringBoot3集成Oauth2.1——8自定义认证模式(密码模式)