天津城市基础设施建设投资集团有限公司网站,培训学校地址网站建设,网站建设费 无形资产,南昌知名网站建设公司#x1f337; 古之立大事者#xff0c;不惟有超世之才#xff0c;亦必有坚忍不拔之志 #x1f390; 个人CSND主页——Micro麦可乐的博客 #x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程#xff0c;入门到实战 #x1f33a;《RabbitMQ》… 古之立大事者不惟有超世之才亦必有坚忍不拔之志 个人CSND主页——Micro麦可乐的博客 《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程入门到实战 《RabbitMQ》专栏19年编写主要介绍使用JAVA开发RabbitMQ的系列教程从基础知识到项目实战 《设计模式》专栏以实际的生活场景为案例进行讲解让大家对设计模式有一个更清晰的理解 《开源项目》本专栏主要介绍目前热门的开源项目带大家快速了解并轻松上手使用 ✨《开发技巧》本专栏包含了各种系统的设计原理以及注意事项并分享一些日常开发的功能小技巧 《Jenkins实战》专栏主要介绍JenkinsDocker的实战教程让你快速掌握项目CI/CD是2024年最新的实战教程 《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧代码样例完整 《Spring Security》专栏中我们将逐步深入Spring Security的各个技术细节带你从入门到精通全面掌握这一安全技术 如果文章能够给大家带来一定的帮助欢迎关注、评论互动 前端函数防抖Debounce完整讲解 - 从原理、应用到完整实现 1. 前言2. 为什么使用防抖3. 函数防抖的应用场景4. 完整代码实现❶ 基础防抖函数❷ 使用示例输入框搜索❸ React Hooks 防抖实现❹ 使用 Lodash 的 _.debounce 5. 高阶技巧与注意事项6. 结语 1. 前言
在我们日常前端开发中高频触发的事件如输入框输入、窗口缩放、滚动事件可能导致性能问题甚至引发BUG。函数防抖debounce是一种常见且高效的性能优化手段用于限制高频事件触发下的函数调用次数从而减少不必要的计算、网络请求或 DOM 操作。
本文博主将带着小伙伴一起深入解析防抖机制的原理、六大应用场景并提供可直接复用的代码示例。 2. 为什么使用防抖 我们来看看你是否也遇到这样的问题
当用户快速连续触发事件时例如 搜索框每输入一个字符立即请求接口窗口缩放时频繁更新布局疯狂点击提交按钮 会导致 性能浪费不必要的计算/请求数据错乱异步请求响应顺序不可控用户体验差界面卡顿或闪烁 函数防抖的核心思想是在连续触发的事件停止后仅执行最后一次调用以避免频繁触发带来的性能问题。 延迟执行 重置计时器在事件被触发后等待指定时间如300ms若期间没有再次触发则执行函数若期间重复触发则重新开始计时 3. 函数防抖的应用场景
场景示例解决方案搜索建议输入框联想词查询停止输入300ms后发起请求按钮提交防止重复提交订单点击后禁用按钮直至操作完成窗口调整响应式布局计算窗口停止调整后执行计算滚动加载无限滚动加载更多停止滚动后触发检测画布绘制实时预览图形渲染停止拖拽后更新渲染表单验证密码强度实时检测输入结束再进行复杂校验
为了让大家更清晰了解其应用场景我们例举几个说明
1、输入框实时搜索 在用户输入关键词时触发搜索接口若不加限制每次 keyup 都会发起请求极易导致接口压力过大。使用防抖后只在用户停止输入如 300ms后才发送请求有效降低调用次数
2、按钮防连点 对于提交表单或支付按钮连续点击可能导致多次提交。给点击事件绑定防抖函数可在用户短时间内多次点击时只执行一次提交操作
3、窗口大小调整resize 当页面布局需根据窗口大小实时计算或重绘时resize 事件会频繁触发添加防抖能减少重绘次数提升性能
4、滚动监听 结合无限滚动或懒加载当用户滚动页面时应控制数据加载频率避免重复请求或过度渲染 4. 完整代码实现
防抖函数通过内部维护一个定时器 ID每次调用时先清除之前的定时器再启动一个新的延迟执行定时器只有在最后一次调用后的延迟时间到达后才真正执行目标函数
❶ 基础防抖函数
先看一个简单实现
/*** 防抖函数* param {Function} fn 需要防抖的函数* param {number} delay 延迟时间毫秒* returns {Function} 包装后的防抖函数*/
function debounce(fn, delay 300) {let timer nullreturn function(...args) {// 每次触发时清除之前的计时器if (timer) clearTimeout(timer)// 设置新的计时器timer setTimeout(() {fn.apply(this, args) // 确保正确的this上下文timer null}, delay)}
}上述代码利用 JavaScript 闭包让每个防抖函数维护独立的 timeoutId在多次调用时只有最后一次延迟结束后触发 ❷ 使用示例输入框搜索
input typetext idsearchInputscript
const searchInput document.getElementById(searchInput)// 原始请求函数
function fetchSearchResult(keyword) {console.log(搜索关键词: ${keyword})// 实际调用API接口...
}// 包装为防抖版本500ms延迟
const debouncedFetch debounce(fetchSearchResult, 500)// 绑定输入事件
searchInput.addEventListener(input, (e) {debouncedFetch(e.target.value.trim())
})
/script❸ React Hooks 防抖实现
import { useCallback, useEffect, useRef } from react// 自定义防抖Hook
function useDebounce(fn, delay) {const timerRef useRef(null)const debouncedFn useCallback((...args) {if (timerRef.current) clearTimeout(timerRef.current)timerRef.current setTimeout(() {fn(...args)timerRef.current null}, delay)}, [fn, delay])// 组件卸载时清除计时器useEffect(() {return () {if (timerRef.current) clearTimeout(timerRef.current)}}, [])return debouncedFn
}// 在组件中使用
function SearchBox() {const [keyword, setKeyword] useState()// 防抖请求函数const debouncedSearch useDebounce((value) {console.log(实际搜索:, value)}, 500)const handleChange (e) {setKeyword(e.target.value)debouncedSearch(e.target.value)}return input value{keyword} onChange{handleChange} /
}❹ 使用 Lodash 的 _.debounce
在实际项目中为了减少手写错误并获得更丰富的功能如 leading、trailing、cancel、flush 等选项推荐使用成熟的工具库 Lodash 的 _.debounce 方法
# 安装 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() 方法可在需要时取消或立即执行待定调用 5. 高阶技巧与注意事项 立即执行模式 在不使用Lodash库时我们也可以添加立即执行选项首次触发立即执行后续触发进入防抖 function debounce(fn, delay, immediate false) {let timerreturn function(...args) {if (immediate !timer) fn.apply(this, args)if (timer) clearTimeout(timer)timer setTimeout(() {if (!immediate) fn.apply(this, args)timer null}, delay)}
}防抖与节流区别 防抖Debounce等电梯最后一个人进来后等10秒关门节流Throttle发短信每60秒只能发一次 性能优化 高频事件如mousemove建议结合requestAnimationFrame避免在防抖函数中处理大型对象 6. 结语
函数防抖是前端性能优化中的一项基础技术适用于各种需要限制高频事件调用的场景通过本文介绍的 定时器逻辑 或成熟的 Lodash 工具库就能快速落地。通过本文的代码示例小伙伴们可以快速将其应用到实际项目中。当遇到高频触发事件时不妨先思考这个场景是否需要防抖
如果你在实践过程中有任何疑问或更好的扩展思路欢迎在评论区留言最后希望大家 一键三连 给博主一点点鼓励 前端技术专栏回顾
01【前端技术】 ES6 介绍及常用语法说明 02【前端技术】标签页通讯localStorage、BroadcastChannel、SharedWorker的技术详解 03 前端请求乱序问题分析与AbortController、async/await、Promise.all等解决方案 04 前端开发中深拷贝的循环引用问题从问题复现到完美解决 05 前端AJAX请求上传下载进度监控指南详解与完整代码示例 06 TypeScript 进阶指南 - 使用泛型与keyof约束参数 07 前端实现视频文件动画帧图片提取全攻略 - 附完整代码样例