一、前言
在 Vue 项目开发中,输入框实时搜索、页面滚动、按钮频繁点击、窗口缩放等操作,会触发高频事件执行。如果每次触发都直接发起接口请求或执行逻辑,会造成大量无效请求、频繁渲染,极大加重浏览器和服务器压力,导致页面卡顿、性能变差。
Lodash 是前端高频工具库,内置成熟的 debounce(防抖) 和 throttle(节流) 方法,能够优雅限制事件触发频率,是 Vue 项目性能优化的常规主流方案。
二、防抖与节流核心原理与场景区分
1. debounce 防抖
核心机制:事件触发后,延迟指定时间执行回调;若延迟期间再次触发事件,会重置计时,直至停止触发、计时走完,才会真正执行一次回调。
通俗理解:连续操作不执行,停下来等一会再执行。
适用场景:输入框实时搜索、窗口大小拖拽缩放、表单实时校验、输入联想查询。
2. throttle 节流
核心机制:事件持续触发时,固定时间间隔内仅执行一次,无论期间触发多少次,都按频率均匀执行,不会无限触发。
通俗理解:持续操作时,每隔一段时间执行一次,匀速限流。
适用场景:页面滚动监听、按钮频繁点击防重、拖拽移动、高频resize监听。
三、Lodash 安装方式
支持 Vue2 / Vue3 全版本,安装命令统一如下:
npm install lodash
使用时按需引入防抖、节流方法,无需全局引入,有效减少项目打包体积,符合轻量化开发规范。
四、Vue2 实战:Lodash 防抖与节流
1. debounce 防抖(输入框实时搜索)
业务场景:输入框实时输入关键词,原生写法每输入一个字符就发起一次请求,产生大量无效请求。防抖优化后,用户持续输入不请求,停止输入300ms后仅执行一次请求,大幅优化性能。
优化说明:移除无效外网测试接口,采用本地模拟数据,代码可直接运行测试,上线后替换真实接口即可。
<template>
<div class="search-box">
<input
v-model="searchQuery"
placeholder="请输入关键词搜索"
/>
<ul>
<li v-for="result in searchResults" :key="result.id">
{{ result.name }}
</li>
</ul>
</div>
</template>
<script>
// 按需引入防抖方法
import { debounce } from 'lodash'
export default {
data() {
return {
searchQuery: '', // 搜索关键词
searchResults: [], // 搜索结果列表
// 本地模拟搜索数据源
searchList: [
{ id: 1, name: 'Vue2 实战教程' },
{ id: 2, name: 'Vue3 语法糖详解' },
{ id: 3, name: 'Lodash 性能优化' },
{ id: 4, name: '前端性能优化指南' }
]
}
},
watch: {
// 监听关键词变化,包裹防抖函数,延迟300ms执行
searchQuery: debounce(function (newQuery) {
this.fetchSearchResults(newQuery)
}, 300)
},
methods: {
// 搜索筛选方法(本地模拟,可直接运行)
fetchSearchResults(query) {
// 空关键词清空列表
if (!query) {
this.searchResults = []
return
}
// 本地模糊匹配筛选
this.searchResults = this.searchList.filter(item => item.name.includes(query))
}
}
}
</script>
2. throttle 节流(页面滚动监听)
业务场景:浏览器滚动会高频触发scroll事件,频繁执行逻辑易造成页面卡顿。通过节流限制执行频率,每300ms仅执行一次逻辑,保证页面滚动流畅。
<template>
<div>
<p>当前滚动高度:{{ scrollPosition }}</p>
<div style="height: 2000px; background: #f0f0f0;">
滚动页面测试节流效果
</div>
</div>
</template>
<script>
// 按需引入节流方法
import { throttle } from 'lodash'
export default {
data() {
return {
scrollPosition: 0,
scrollHandle: null // 存储节流函数实例,用于销毁取消
}
},
mounted() {
// 封装节流方法并存储实例
this.scrollHandle = throttle(function () {
this.scrollPosition = window.scrollY
}, 300)
// 挂载时绑定滚动事件
window.addEventListener('scroll', this.scrollHandle)
},
beforeDestroy() {
// 组件销毁:移除监听 + 取消防流,彻底释放资源,杜绝内存泄漏
window.removeEventListener('scroll', this.scrollHandle)
this.scrollHandle.cancel()
}
}
</script>
五、Vue3 Setup 语法糖专属写法(主流推荐)
Vue3 组合式API + setup语法糖是目前项目主流写法,适配Vue3全版本,代码更简洁、逻辑更集中,下面提供可直接上线的防抖、节流完整案例,全部适配本地测试,无接口依赖。
1. Vue3 防抖实战(实时搜索)
<template>
<div class="search-box">
<input v-model="searchQuery" placeholder="Vue3 防抖搜索" />
<div v-for="item in searchList" :key="item.id">{{ item.title }}</div>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
// 按需引入lodash防抖
import { debounce } from 'lodash'
// 定义响应式数据
const searchQuery = ref('')
const searchList = ref([])
// 本地模拟数据源
const sourceData = ref([
{ id: 1, title: 'Vue3 组合式API' },
{ id: 2, title: 'Lodash 防抖节流' },
{ id: 3, title: '前端性能优化' },
{ id: 4, title: 'Vue项目实战优化' }
])
// 封装搜索筛选方法(本地模拟,可直接运行)
const getSearchData = (val) => {
if (!val) {
searchList.value = []
return
}
// 本地模糊匹配
searchList.value = sourceData.value.filter(item => item.title.includes(val))
}
// 防抖监听:延迟300ms执行,避免高频触发
const debounceSearch = debounce(getSearchData, 300)
watch(searchQuery, (newVal) => {
debounceSearch(newVal)
})
</script>
2. Vue3 节流实战(滚动监听+按钮防重)
包含两大高频场景:页面滚动节流、按钮重复点击节流,完美解决Vue3项目高频操作性能问题,自带销毁逻辑,零内存泄漏。
<template>
<div>
<p>页面滚动高度:{{ scrollTop }}</p>
<button @click="submitHandle">提交表单(节流防重)</button>
<div style="height: 2000px;background: #f5f5f5;margin-top: 20px;">滚动测试区域</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { throttle } from 'lodash'
const scrollTop = ref(0)
// 1. 滚动节流函数 300ms执行一次
const scrollHandle = throttle(() => {
scrollTop.value = window.scrollY
}, 300)
// 2. 按钮点击节流 1s内仅可点击一次(防重复提交)
const submitHandle = throttle(() => {
console.log('执行表单提交逻辑,请求接口')
// 可在此处写接口请求、表单提交等业务逻辑
}, 1000)
// 挂载绑定事件
onMounted(() => {
window.addEventListener('scroll', scrollHandle)
})
// 销毁移除事件,杜绝内存泄漏
onUnmounted(() => {
window.removeEventListener('scroll', scrollHandle)
// 取消节流监听,释放资源
scrollHandle.cancel()
})
</script>
3. Vue3 核心注意点
- Vue3 setup语法中,防抖/节流函数需单独封装变量接收,避免直接写在watch内部导致销毁异常、逻辑失效
- 高频全局事件(scroll、resize),必须在
onUnmounted中移除监听、调用cancel()取消节流防抖 - 按钮防重提交推荐设置 1000ms 节流间隔,有效防止用户快速重复点击、重复提交表单
- 支持调用
cancel()方法手动取消防抖/节流,灵活适配弹窗关闭、页面跳转等复杂业务场景
六、防抖 & 节流核心总结
| 方法 | 执行逻辑 | 核心特点 | 常用场景 |
|---|---|---|---|
| debounce 防抖 | 停止操作后延迟执行,连续操作重置计时 | 多次触发,只执行最后一次 | 搜索框联想、输入校验、窗口缩放 |
| throttle 节流 | 固定间隔匀速执行,持续触发不叠加 | 限定频率,间隔执行 | 页面滚动、按钮防重、拖拽操作 |
七、开发避坑与最佳实践
- 场景区分:高频输入联想、实时校验用防抖;持续触发的滚动、点击、拖拽事件用节流
- 时间规范:常规防抖/节流延迟默认 300ms,按钮防重、表单提交推荐 1000ms
- 内存优化(重中之重) :所有全局绑定的高频事件,组件销毁必须移除监听、手动 cancel 取消防抖节流,彻底杜绝内存泄漏
- 写法规范:Vue3 优先使用组合式API单独封装防抖节流函数,代码解耦、方便销毁、更易维护
- 性能最优:优先按需引入lodash单个方法,不全局导入整个库,有效减小项目打包体积
- 测试规范:本地开发优先使用模拟数据测试功能,上线后替换真实业务接口,避免无效接口报错
- 手动取消:弹窗关闭、页面跳转、数据重置场景,可主动调用
cancel()终止防抖节流监听,避免无效执行