自学内容网 自学内容网

使用防抖与节流优化 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>

问题分析

  1. 频繁触发: 如果用户快速点击复选框,会多次触发 @change 事件,每次都会调用异步函数,可能导致性能问题或资源浪费。
  2. 异步处理: 异步函数无法同步返回结果,可能会引发状态更新问题。

为了解决这些问题,我们可以使用防抖和节流技术。


防抖(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)!