uni.setStorageSync 存数组需先读再写防覆盖,正确流程为读取、去重、插头、截取;onLoad读、onUnload存;v-model名须一致;清空历史需三步:删存储、置空数组、forceUpdate。
uni.setStorageSync 是可行的,但直接调用它存数组大概率出问题——不是数据丢了,就是重复、顺序乱、安卓光标不聚焦、iOS真机读不到。
为什么每次存历史都得先读再写?
因为 uni.setstoragesync 是覆盖写入,不是追加。你写 uni.setstoragesync('searchhistory', ['苹果']),下次再写 uni.setstoragesync('searchhistory', ['香蕉']),前者就彻底没了。
真正安全的流程是:
- 用
uni.getStorageSync('searchHistory')拿出旧数组(注意加默认值:|| []) - 检查新词是否已存在(大小写归一化比对:
item.toLowerCase() === keyword.toLowerCase()) - 存在就先
splice(index, 1)删除,再unshift(keyword)插到开头 - 不存在就直接
unshift(keyword) - 最后
slice(0, 10)截取前 10 条,避免无限膨胀
onLoad 里读、onUnload 里存,别在 @input 里狂写
@input 频率太高,每敲一个字都触发 uni.setStorageSync,低端安卓会卡顿,小程序后台切走还可能丢数据。
正确时机只有两个:
-
onLoad或onShow:读取历史并赋值给data,确保页面一打开就有列表 -
onUnload:用户离开搜索页时统一保存,覆盖左滑返回、tab 切走、点击搜索跳转等所有路径
别在 @confirm 里边发请求边存——网络慢时请求成功了,存储却没执行完;更别在防抖函数里调 uni.setStorageSync,它可能被取消。
v-model 绑定名不一致,点历史词就没反应
这是最常被忽略的“静默失败”:你在 handleHistoryClick 里写了 this.searchValue = word,但 input 上是 v-model="searchText" ——变量名对不上,UI 根本不会更新。
检查这三点:
-
v-model绑定的变量名和赋值语句是否完全一致(大小写、下划线、拼写) - 赋值后加
this.$nextTick(() => this.$refs.inputRef?.focus()),尤其安卓真机需要手动聚焦 - 如果用了防抖,点击历史词后记得
clearTimeout(this.timer),否则可能延迟触发旧搜索
清空历史后 UI 不刷新?试试 this.$forceUpdate()
调用 uni.removeStorageSync('search_history') 只删了存储,data 里的数组引用还是旧的。H5 和 App 环境下 Vue2 对空数组响应不敏感,UI 常常卡住不动。
清空必须三步到位:
- 执行
uni.removeStorageSync('search_history') - 把 data 中的历史数组设为空:
this.historyList = [] - 手动触发更新:
this.$forceUpdate()(仅 Vue2 项目需要)
另外,别用 :key="item" 渲染历史项——重复词 key 冲突会导致 Vue 复用错误节点;改用索引::key="index"。


















