uni-app中用原生input实现搜索联想需手动叠加view列表,关键在防抖(setTimeout+clearTimeout延迟300ms)和触发时机,输入长度

uni-app里怎么用 input 实现搜索联想(非组件库)
原生 input 组件不支持下拉联想,必须手动叠加 view 列表 + 控制显隐。关键不是“怎么显示”,而是“什么时候触发请求”和“怎么防抖”。直接在 @input 里发请求,用户还没打完字就刷出一堆错误结果,还可能把后端打挂。
实操建议:
- 用
setTimeout+clearTimeout做简单防抖,延迟 300ms 再调接口;别用节流,用户删字时也得重新查 - 输入长度
时直接清空联想列表,避免搜单字返回大量无关词 - 请求前加个 loading 状态,防止用户连点多次;响应后记得清除定时器,否则容易内存泄漏
- 接口返回的联想词建议带权重或热度字段,前端按此排序,别全靠后端返回顺序
搜索历史怎么存进 uni.setStorageSync 并去重
uni.setStorageSync 存数组没问题,但直接 push 再保存,历史会无限膨胀,且重复词越积越多。更麻烦的是,用户搜了“苹果”,又搜“苹果手机”,再搜“苹果”,三个都留着,体验很糙。
实操建议:
- 每次新增前先用
filter去重:history = history.filter(item => item !== newWord),再unshift插入头部 - 限制最大条数(比如 10 条),超出后
history.pop()删尾部,别用splice(0, -1)这种易错写法 - 存之前对关键词做
.trim(),避免“苹果 ”和“苹果”被当两个词 - 如果想支持模糊匹配历史(比如输入“苹”就显示“苹果”),得额外建索引数组,别现场
includes查,性能差
为什么联想列表点击后没清空输入框或没跳转
常见现象是点了联想词,输入框内容没变,或者变了但没触发搜索逻辑。根本原因在于:你只改了 v-model 绑定的变量,但没同步调用搜索函数,也没处理焦点丢失逻辑。
实操建议:
- 点击联想项时,先赋值
searchValue = item,再立刻调用搜索方法(如doSearch()),别等@confirm或回车 - 点击后手动调用
uni.hideKeyboard(),不然键盘盖住列表,用户以为没反应 - 如果用了
focus属性控制输入框聚焦状态,记得点击后设focus = false,否则光标还在闪,干扰下一步操作 - 安卓真机上有时
input的confirm-type="search"不触发@confirm,得靠点击事件兜底
缓存历史记录在多端表现不一致?
uni.getStorageSync 在微信小程序、App、H5 都可用,但行为有差异:H5 用的是 localStorage,App 是本地文件,微信小程序是封闭存储。最常踩的坑是——H5 切换域名或清缓存后历史全丢,而小程序不会。
实操建议:
- 不要依赖缓存绝对存在,读取时加 try/catch,失败就用空数组兜底:
try { history = uni.getStorageSync('searchHistory') || [] } catch(e) { history = [] } - 如果需要跨端持久化更强,可考虑把历史同步到后端,但得权衡隐私合规问题(比如 GDPR)
- App 端注意
uni.setStorageSync有 10MB 上限,纯文本历史基本不超,但若混存了 base64 图片之类,就容易爆 - 微信小程序开发工具里缓存有时不实时刷新,真机调试前记得先清缓存再测
搜索联想和历史缓存看着简单,真正卡住人的往往是防抖时机、去重逻辑和多端存储边界。别急着封装成组件,先把这三块在页面里跑通,再抽离。


















