防抖实现搜索框自动联想:监听searchKey变化,输入停止300ms后请求,支持取消旧定时器,配合loading、suggestions状态及空值校验优化体验。

用 watch 实现搜索框自动联想,核心是监听输入变化、控制请求频率、避免无效请求。关键不在“监听”,而在“何时发请求”——防抖(debounce)负责等用户停手再查,节流(throttle)适合高频但需定期响应的场景,搜索联想中防抖更常用。
监听输入并触发防抖查询
使用 Vue 的 watch 监听搜索关键词(如 searchKey),每次变化不立即调接口,而是重置防抖定时器。只有用户停止输入一段时间(如 300ms)后,才执行搜索建议逻辑。
- 在
setup中定义响应式关键词:const searchKey = ref('') watch(searchKey, debounce(() => fetchSuggestions(), 300))- 注意:
debounce需自行实现或引入工具库(如 Lodash),且要确保能清除上一次定时器
手写一个轻量防抖函数(支持取消)
避免闭包中旧值导致请求错乱(比如输入“a”→快速删掉改输“abc”,结果却返回“a”的联想),防抖函数必须支持取消待执行任务。
- 返回一个可取消的函数:
function debounce(fn, delay) { let timer = null; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } - 进阶:暴露
cancel方法,便于在组件卸载或关键词清空时主动清理 - Vue 3 中可在
onBeforeUnmount调用 cancel,防止内存泄漏或报错
结合 loading 和空状态做体验优化
用户输入时显示加载态,无结果时提示“暂无建议”,有结果则渲染下拉列表——这些状态都应受控于 watch 触发的逻辑链。
- 定义
const loading = ref(false)、const suggestions = ref([]) - 在防抖回调中:设
loading.value = true→ 调接口 → 更新suggestions→ 设loading.value = false - 若用户快速连续输入,前序请求可能后到,可用请求标识(如时间戳或 AbortController)丢弃过期响应
避免重复请求和无效联想
不是所有输入都要查:空字符串、纯空格、长度<2 的词通常无需请求;已缓存的结果可直接复用,减少服务端压力。
- 在防抖回调开头加守卫:
if (!searchKey.value.trim() || searchKey.value.length - 用 Map 或对象缓存历史请求:
const cache = new Map(); const key = searchKey.value.trim(); if (cache.has(key)) { suggestions.value = cache.get(key); return; } - 接口返回后,存入缓存:
cache.set(key, data)(注意缓存大小和过期策略)
防抖 + watch 是搜索联想最自然的组合,节流反而容易造成联想延迟或遗漏。重点是让请求“聪明”:等得恰到好处、记得住上次、懂得及时刹车。











