防抖与节流

84 阅读4分钟

防抖与节流:Vue3+TS 实战指南

作为一个常被产品经理吐槽"页面卡成PPT"的程序员,今天带你彻底掌握两个让页面飞起来的神器:节流(Throttle)防抖(Debounce)。本文使用 Vue3 + TypeScript + Vite + VueUse 实战演示,无需造轮子,直接上手!


一、为什么页面会卡顿?

先看两个典型场景:

  1. 搜索框场景

    用户每输入一个字母就发起请求,输入"前端开发"(4字)触发 8 次请求 → 服务器压力巨大

  2. 滚动加载场景

    用户滚动鼠标时,代码疯狂计算,页面卡顿如PPT

解决方案:节流和防抖就像"交通管理员",精准控制请求频率,让页面丝滑如丝绸。


二、核心区别

🧠 核心区别:执行时机不同

特性防抖 (Debounce)节流 (Throttle)
执行时机最后一次触发后等待一段时间才执行每隔一段时间执行一次
执行次数无论触发多少次,最终只执行1次每个时间间隔内最多执行1次
触发逻辑"等你停手了,我再行动""按固定频率执行,拒绝插队"
典型比喻电梯关门:最后一个人进来后3秒关门地铁发车:每5分钟一班,必须等5分钟

💡 关键理解

防抖关注"最终结果",节流关注"执行频率"

(搜索要结果,滚动要过程)


三、场景选择

场景推荐方式为什么?实际案例
搜索框输入✅ 防抖用户输入结束再请求,避免无效请求电商网站搜索框
**页面滚动 **✅ 节流需持续响应滚动动作无限滚动加载
按钮点击✅ 节流防止用户快速连续点击提交按钮、点赞按钮
表单实时验证✅ 防抖输入结束再验证,避免干扰用户用户名/邮箱格式校验
实时输入监听✅ 防抖需要实时响应输入变化密码强度提示

💡 一句话总结

要结果用防抖,要过程用节流

(搜索要结果,滚动要过程)


四、实战

✅ 无需手写,对于Vue3工程,可以直接使用 VueUse 组件

npm install @vueuse/core

1. 防抖(Debounce)

1. 使用示例
<template>
  <div>
    <el-input
      v-model="keyword"
      @blur="debouncedSearch"
      placeholder="搜索点什么..."
      style="width: 300px"
    />
    <p>搜索关键词:{{ keyword }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useDebounceFn } from '@vueuse/core'

const keyword = ref('')

const searchAPI = () => console.log('发起搜索请求时间:', new Date().toLocaleString())

const debounce = useDebounceFn(() => searchAPI(), 1000)
const debouncedSearch = () => {
  debounce()
  console.log('失去焦点的时间:', new Date().toLocaleString())
}
</script>

image-20251228165625344

2. useDebounceFn函数用法

image-20251229204223710

参数名类型默认值说明
fn(...args: any[]) => any必填需要防抖的原始函数
msnumber0防抖延迟(毫秒),停手多少 ms 后才执行 fn
optionsDebounceFilterOptions见下方高级行为配置对象(可选)
DebounceFilterOptions 子项
选项名类型默认值说明
maxWaitnumberundefined最大等待时间,超时必执行
rejectOnCancelbooleanfalse手动 cancel() 后,promise() 是否 reject 而不是一直 pending
返回值附加方法
方法名含义
debounced(...args)正常触发,防抖生效
debounced.cancel()取消当前计时,不会执行原函数
debounced.flush()立即执行原函数并清空计时
debounced.promise(...args)返回 Promise,resolve 原函数返回值

2. 节流(Throttle)

1. 使用示例
<template>
  <div>
    <el-button type="primary" @click="throttleSearch">点击</el-button>
  </div>
</template>

<script setup lang="ts">
import { useThrottleFn } from '@vueuse/core'
const searchAPI = () => console.log('发起搜索请求时间:', new Date().toLocaleString())

const throttle = useThrottleFn(() => searchAPI(), 1000)

let count = 0
const throttleSearch = () => {
  throttle()
  console.log(`点击了${++count}次`)
}
</script>

image-20251229203827523

2. useThrottleFn函数用法

image-20251228171858407

参数名类型默认值说明
fn(...args: any[]) => any必填需要被节流包装的原始函数
msnumber0节流间隔(毫秒),在该时间段内最多执行一次 fn
optionsThrottleFnOptions见下方高级行为配置对象(可选)
ThrottleFnOptions 子项
选项名类型默认值说明
leadingbooleantrue是否在节流周期开始立即执行一次原函数
trailingbooleanfalse是否在节流周期结束再执行一次原函数
rejectOnCancelbooleanfalse手动 cancel() 后,promise() 是否 reject
返回值函数
方法名含义
throttled(...args)正常触发,节流生效
throttled.cancel()取消当前计时,不会执行原函数
throttled.flush()立即执行原函数并清空计时
throttled.promise(...args)返回 Promise,resolve 原函数返回值

五、口诀

技术核心思想适用场景一句话总结
防抖等你停手了,我再行动搜索、表单验证要结果,别急着动
节流按固定频率执行滚动、拖拽要过程,别太急

总结

节流和防抖是前端性能的"刹车系统"

✅ 用对 = 页面丝滑如丝绸

❌ 用错 = 服务器崩溃+产品经理暴怒

建议收藏本文,下次产品说"页面卡"时,先检查是否忘了加防抖/节流! 😄