Vue3 + Vite 中使用 Lodash-es 的防抖 debounce 详解_lodash-es debounce
Vue3 + Vite 中使用 Lodash-es 的防抖(debounce)详解
在 Vue3 + Vite 项目中,debounce
是 lodash-es 中最常用的功能之一,它可以帮助我们优化高频事件的处理。下面我将详细讲解 debounce 的使用方法,并提供一个完整的示例。
Debounce 核心概念
防抖(debounce) 是一种优化高频操作的技术。它会将多次连续的操作合并为一次,确保函数在指定时间间隔内只执行一次。
适用场景
-
搜索框输入建议
-
窗口大小调整事件
-
滚动事件处理
-
表单验证
在 Vue3 中使用 Debounce
安装 lodash-es
bash
复制
下载
npm install lodash-es
Debounce 参数详解
基本语法
javascript
复制
下载
const debouncedFunc = debounce(func, [wait=0], [options={}])
参数说明
-
func
(Function): 要防抖的函数 -
[wait=0]
(number): 延迟的毫秒数 -
[options={}]
(Object): 选项对象 -
[options.leading=false]
(boolean): 指定在延迟开始前调用 -
[options.trailing=true]
(boolean): 指定在延迟结束后调用 -
[options.maxWait]
(number): 设置 func 允许被延迟的最大时间
选项说明
-
leading: true (立即执行模式)
-
第一次触发时立即执行
-
后续在等待时间内触发不会执行
-
等待时间结束后再次触发会再次立即执行
-
-
trailing: true (延迟执行模式 - 默认)
-
第一次触发后开始计时
-
在等待时间内再次触发会重置计时器
-
等待时间结束后执行最后一次操作
-
-
maxWait (最大等待时间)
-
确保函数在指定时间内至少执行一次
-
即使连续触发也不会超过这个时间间隔
-
在 Vue3 中使用 Debounce 的最佳实践
1. 在 setup 中创建防抖函数
javascript
复制
下载
import { debounce } from \'lodash-es\'// 在 setup 中创建防抖函数const debouncedFunction = debounce(() => { // 你的逻辑}, 300)
2. 组件卸载时取消防抖
javascript
复制
下载
import { onUnmounted } from \'vue\'onUnmounted(() => { debouncedFunction.cancel()})
3. 在模板中使用
vue
复制
下载
4. 处理带参数的函数
javascript
复制
下载
const debouncedSearch = debounce((searchTerm) => { // 使用 searchTerm}, 500)// 在事件处理中const handleInput = (e) => { debouncedSearch(e.target.value)}
5. 使用立即执行模式(leading)
javascript
复制
下载
const handleClick = debounce(() => { // 处理点击}, 1000, { leading: true, trailing: false })
注意事项
-
避免重复创建:不要在每次渲染时创建新的 debounce 函数,否则会失去防抖效果
-
组件卸载时取消:防止内存泄漏和意外执行
-
合理设置等待时间:
-
搜索建议:200-500ms
-
窗口调整:100-300ms
-
按钮点击:1000ms(防止重复提交)
-
-
与 async/await 一起使用:
javascript
复制
下载
const debouncedAsync = debounce(async (param) => { const result = await fetchData(param) // 处理结果}, 300)
这个示例展示了在 Vue3 + Vite 项目中如何有效地使用 lodash-es 的 debounce 功能,涵盖了多种使用场景和配置选项。
Lodash-es Debounce 使用演示
搜索结果: {{ searchResults }} 调整窗口大小查看效果 窗口大小: {{ windowSize.width }} x {{ windowSize.height }}
import { ref, onMounted, onUnmounted } from \'vue\'import { debounce } from \'lodash-es\'// 搜索相关状态const searchTerm = ref(\'\')const searchResults = ref(\'\')// 防抖处理搜索输入const handleSearchInput = debounce(() => { searchResults.value = `正在搜索: \"${searchTerm.value}\"...` console.log(\'执行搜索:\', searchTerm.value)}, 500)// 窗口大小相关状态const windowSize = ref({ width: window.innerWidth, height: window.innerHeight })// 防抖处理窗口大小变化const handleResize = debounce(() => { windowSize.value = { width: window.innerWidth, height: window.innerHeight } console.log(\'窗口大小更新:\', windowSize.value)}, 300)// 监听窗口大小变化onMounted(() => { window.addEventListener(\'resize\', handleResize)})// 组件卸载时移除监听器onUnmounted(() => { window.removeEventListener(\'resize\', handleResize)})// 按钮点击相关状态const clickCount = ref(0)// 防抖处理按钮点击(带立即执行选项)const handleButtonClick = debounce(() => { clickCount.value += 1 console.log(\'按钮点击处理\', clickCount.value)}, 1000, { leading: true, trailing: false }).container { max-width: 800px; margin: 0 auto; padding: 2rem; font-family: \'Segoe UI\', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #f5f7fa, #e4edf9); min-height: 100vh; border-radius: 12px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);}h1 { color: #2c3e50; text-align: center; margin-bottom: 2rem; border-bottom: 2px solid #3498db; padding-bottom: 1rem;}.input-group, .resize-group, .button-group { background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); margin-bottom: 2rem;}label { display: block; margin-bottom: 0.5rem; font-weight: 600; color: #34495e;}input { width: 100%; padding: 0.8rem; border: 1px solid #ddd; border-radius: 6px; font-size: 1rem; margin-bottom: 1rem; transition: border 0.3s;}input:focus { border-color: #3498db; outline: none; box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);}.search-result { padding: 1rem; background-color: #e3f2fd; border-radius: 6px; font-weight: 500; color: #2c3e50;}.resize-box { height: 150px; background: linear-gradient(45deg, #3498db, #9b59b6); color: white; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; font-weight: bold; border-radius: 8px; margin-bottom: 1rem; transition: width 0.3s ease;}p { color: #7f8c8d; font-size: 0.95rem;}button { background: #3498db; color: white; border: none; padding: 0.8rem 1.5rem; border-radius: 6px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: background 0.3s, transform 0.2s; display: block; width: 100%; max-width: 300px; margin: 0 auto;}button:hover { background: #2980b9;}button:active { transform: translateY(2px);}.button-group p { text-align: center; margin-top: 1rem; font-size: 1.1rem; font-weight: bold; color: #2c3e50;}