使用防抖与节流优化 Vue 中的异步函数调用
使用防抖与节流优化 Vue 中的异步函数调用
在 Vue 项目中,我们经常需要处理用户交互事件,例如点击、输入、切换复选框等。这些事件可能频繁触发,尤其在用户快速操作的情况下,如果每次触发都执行复杂的逻辑(如异步网络请求),会导致性能问题或不必要的开销。
本文将以一个具体场景为例,详细讲解如何在 Vue 中使用 防抖(Debounce) 和 节流(Throttle) 优化异步函数的调用。
示例场景
假设我们有一个 Vue 组件模板,用于显示一个复选框,每当复选框状态变化时,需要调用异步函数 toggleRowSelection
。
初始代码
<template>
<el-checkbox
:model-value="isRowSelected(scope.row.satellite_id)"
@change="toggleRowSelection(scope.row.satellite_id, $event)"
class="hidden-checkbox-text"
></el-checkbox>
</template>
<script setup lang="ts">
const isRowSelected = (satelliteId: string) => {
// 检查某行是否被选中
return selectedSatellites.value.includes(satelliteId)
}
const toggleRowSelection = async (satelliteId: string, isChecked: boolean) => {
// 异步处理逻辑
await someAsyncOperation(satelliteId, isChecked)
}
</script>
问题分析
- 频繁触发: 如果用户快速点击复选框,会多次触发
@change
事件,每次都会调用异步函数,可能导致性能问题或资源浪费。 - 异步处理: 异步函数无法同步返回结果,可能会引发状态更新问题。
为了解决这些问题,我们可以使用防抖和节流技术。
防抖(Debounce)
防抖的概念是:只有在事件触发后的一段时间内未再触发,才会执行对应的操作。适用于用户停止触发后执行操作的场景。
使用场景
在我们的例子中,如果用户快速连续点击复选框,我们只关心最后一次点击的状态。此时,防抖是一个合适的选择。
实现步骤
安装 lodash
使用防抖需要引入工具库,例如 lodash
。先安装:
npm install lodash
改造代码
在组件中,使用 lodash 的 debounce
包装异步函数。
import { debounce } from 'lodash'
const toggleRowSelection = debounce(async (satelliteId: string, isChecked: boolean) => {
try {
await someAsyncOperation(satelliteId, isChecked)
} catch (error) {
console.error('Error in toggleRowSelection:', error)
}
}, 300) // 防抖时间为 300 毫秒
模板中:
<el-checkbox
:model-value="isRowSelected(scope.row.satellite_id)"
@change="toggleRowSelection(scope.row.satellite_id, $event)"
class="hidden-checkbox-text"
></el-checkbox>
效果
- 如果用户快速点击复选框,只有停止操作后 300 毫秒,
toggleRowSelection
才会执行。 - 避免了不必要的异步调用,提升了性能。
节流(Throttle)
节流的概念是:无论事件触发多频繁,都只在规定的时间间隔内执行一次操作。适用于需要限制触发频率的场景。
使用场景
在我们的例子中,如果希望用户快速连续点击时,仍能定期同步状态,而不是等待操作停止,可以使用节流。
实现步骤
改造代码
使用 lodash 的 throttle
实现节流。
import { throttle } from 'lodash'
const toggleRowSelection = throttle(async (satelliteId: string, isChecked: boolean) => {
try {
await someAsyncOperation(satelliteId, isChecked)
} catch (error) {
console.error('Error in toggleRowSelection:', error)
}
}, 1000) // 节流时间为 1000 毫秒
模板中:
<el-checkbox
:model-value="isRowSelected(scope.row.satellite_id)"
@change="toggleRowSelection(scope.row.satellite_id, $event)"
class="hidden-checkbox-text"
></el-checkbox>
效果
- 即使用户快速连续点击复选框,
toggleRowSelection
最多每秒执行一次。 - 限制了异步操作的调用频率,避免系统压力过大。
防抖与节流的区别
特性 | 防抖(Debounce) | 节流(Throttle) |
---|---|---|
工作原理 | 在事件触发结束后延时执行 | 在固定时间间隔内执行一次操作 |
适用场景 | 希望操作在事件触发停止后才执行 | 希望限制操作执行的频率 |
示例场景 | 输入框搜索、快速点击后最后一次有效操作 | 滚动事件、按钮防重复点击 |
可能的影响 | 延迟执行,可能导致响应性变差 | 忽略部分触发,可能导致操作不够灵敏 |
防抖 + 节流结合使用
在某些复杂场景中,防抖和节流可以结合使用。例如,既希望响应最后一次操作,又希望在高频率触发时保持操作稳定。
示例代码
import { debounce, throttle } from 'lodash'
const toggleRowSelection = debounce(throttle(async (satelliteId: string, isChecked: boolean) => {
await someAsyncOperation(satelliteId, isChecked)
}, 1000), 300) // 节流间隔 1000 毫秒,防抖时间 300 毫秒
示例完整代码
Vue 组件模板
<template>
<el-checkbox
:model-value="isRowSelected(scope.row.satellite_id)"
@change="toggleRowSelection(scope.row.satellite_id, $event)"
class="hidden-checkbox-text"
></el-checkbox>
</template>
<script setup lang="ts">
import { debounce } from 'lodash'
const isRowSelected = (satelliteId: string) => {
return selectedSatellites.value.includes(satelliteId)
}
const toggleRowSelection = debounce(async (satelliteId: string, isChecked: boolean) => {
try {
console.log(`Toggling row: ${satelliteId}, Checked: ${isChecked}`)
await someAsyncOperation(satelliteId, isChecked)
} catch (error) {
console.error('Error toggling row selection:', error)
}
}, 300)
</script>
总结
在 Vue 中处理用户交互事件时,防抖和节流可以显著优化性能:
- 使用防抖: 适合只关心用户停止操作后的场景。
- 使用节流: 适合需要限制操作频率的场景。
- 结合使用: 在复杂场景中,可以同时使用防抖和节流。
根据实际需求选择合适的优化方式,可以让你的应用更高效、更流畅。
原文地址:https://blog.csdn.net/maply/article/details/145157464
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!