vue 3 中用 watch 配合防抖实现输入框搜索,需定义 searchkey、loading、results 响应式变量,手写 debounce 函数延迟执行请求,watch 监听 searchkey 并调用防抖后的异步搜索函数,模板中绑定 v-model 并展示加载状态与结果。

在 Vue 3 中,用 watch 配合防抖(debounce)实现输入框触发的后端查询,关键在于:不直接在 watch 回调里发请求,而是用防抖函数延迟执行,避免高频请求。下面给出简洁、可复用的写法。
1. 使用 ref 定义搜索关键词和 loading 状态
先在 setup 中定义响应式数据:
注意:不要用 v-model 直接连到一个计算属性或复杂逻辑上,保持输入值干净可监听。
-
searchKey:绑定输入框,类型为ref<string></string> -
loading:用于控制搜索中状态(比如禁用按钮、显示 loading 指示器) -
results:存放接口返回的数据
2. 手写简易防抖函数(或使用 lodash)
推荐手写轻量版,避免引入额外依赖:
防抖的核心是每次触发时清除上一次定时器,只保留最后一次的执行。
const debounce = (fn: Function, delay: number) => {
let timer: NodeJS.Timeout | null = null
return (...args: any[]) => {
if (timer) clearTimeout(timer)
timer = setTimeout(() => fn(...args), delay)
}
}
也可以用 lodash.debounce,但需确保它在 setup 中正确引用(注意:不能直接传入箭头函数给 watch,需提前绑定或封装)。
3. 在 watch 中监听 searchKey 并执行防抖请求
重点来了:把防抖后的请求函数传给 watch,而不是在回调里直接调用 fetch。
- 监听
searchKey变化 - 当值为空字符串时,可清空结果、跳过请求
- 防抖函数内部负责设置
loading = true、调用 API、处理响应、更新results和loading
示例代码:
import { ref, watch } from 'vue'
const searchKey = ref('')
const results = ref([])
const loading = ref(false)
// 防抖请求函数
const searchDebounced = debounce(async () => {
if (!searchKey.value.trim()) {
results.value = []
return
}
loading.value = true
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(searchKey.value)}`)
results.value = await res.json()
} catch (err) {
console.error('搜索失败', err)
} finally {
loading.value = false
}
}, 300)
// 监听关键词变化,触发防抖函数
watch(searchKey, searchDebounced)
4. 模板中绑定与提示
在模板中正常使用 v-model,并展示 loading 或结果:
<input v-model="searchKey" placeholder="输入关键词搜索..."><div v-if="loading">搜索中...</div>
- {{ item.name }}
小技巧:如果需要手动取消未完成的请求(如 AbortController),可在防抖函数内配合 AbortSignal 实现更精细控制,但对多数场景非必需。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









