> 技术文档 > Vue3 + Vite 中使用 Lodash-es 的防抖 debounce 详解_lodash-es debounce

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 允许被延迟的最大时间

选项说明

  1. leading: true (立即执行模式)

    • 第一次触发时立即执行

    • 后续在等待时间内触发不会执行

    • 等待时间结束后再次触发会再次立即执行

  2. trailing: true (延迟执行模式 - 默认)

    • 第一次触发后开始计时

    • 在等待时间内再次触发会重置计时器

    • 等待时间结束后执行最后一次操作

  3. 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 })

注意事项

  1. 避免重复创建:不要在每次渲染时创建新的 debounce 函数,否则会失去防抖效果

  2. 组件卸载时取消:防止内存泄漏和意外执行

  3. 合理设置等待时间

    • 搜索建议:200-500ms

    • 窗口调整:100-300ms

    • 按钮点击:1000ms(防止重复提交)

  4. 与 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 }}

点击次数: {{ clickCount }}

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;}