uni.setStorageSync存数组必须先JSON.stringify,否则静默失败;读取时需JSON.parse并兜底空值;去重置顶需先findIndex再splice+unshift;onShow比onLoad更适合同步缓存;清空历史需setStorageSync空数组而非removeStorageSync。

uni.setStorageSync 存数组前必须 JSON.stringify
直接存数组会报错或读取为空,因为 uni.setStorageSync 只接受字符串作为 value。很多人卡在这一步:明明 this.historyList.unshift(keyword) 看似更新了,但没转成字符串就存,下次 uni.getStorageSync 拿出来的就是 undefined 或空字符串。
- ✅ 正确写法:
uni.setStorageSync('searchHistory', JSON.stringify(this.historyList)) - ❌ 错误写法:
uni.setStorageSync('searchHistory', this.historyList)(静默失败) - 读取时也得配套处理:
const list = JSON.parse(uni.getStorageSync('searchHistory') || '[]') - 注意空值兜底,
|| '[]'防止JSON.parse(undefined)报错
历史记录去重 + 置顶逻辑不能只靠 unshift
用户搜“苹果”→“香蕉”→再搜“苹果”,理想效果是“苹果”回到第一位,“香蕉”往后排。如果每次无脑 unshift,就会出现重复项。必须先查、再删、再插。
- 用
findIndex定位已有关键词:const idx = this.historyList.findIndex(item => item === keyword) - 存在且不在首位时,先
splice(idx, 1)删除旧位置 - 再统一
unshift(keyword)插入开头 - 避免用
includes+filter组合,会破坏顺序且性能略差
onLoad 不是唯一读取时机,onShow 更稳妥
搜索页常被反复进出(比如从结果页返回),onLoad 只触发一次,而 onShow 每次页面显示都执行。若用户在别处清空了缓存,仅靠 onLoad 就无法及时刷新历史列表。
- ✅ 推荐在
onShow中重新读取:this.historyList = JSON.parse(uni.getStorageSync('searchHistory') || '[]') - ⚠️ 注意:如果页面有传参(如带默认关键词),可在
onLoad初始化,onShow负责同步缓存状态 - 小程序真机调试时,
onLoad在冷启动才触发,热切换基本不走,这点容易被忽略
清空历史要同步删 key,别只清空数组
只执行 this.historyList = [] 再调 setStorageSync 是不够的。如果用户手动用开发者工具清除了 storage,或者跨端(如 H5 和小程序)共用 key,残留数据可能还在。
- ✅ 安全清空两步走:
this.historyList = []→uni.setStorageSync('searchHistory', JSON.stringify([])) - ❌ 不要用
uni.removeStorageSync('searchHistory')单独删 key,后续JSON.parse(uni.getStorageSync(...))会因返回null报错 - 如果业务需要「限制最多 10 条」,在插入前加
if (this.historyList.length > 9) this.historyList.pop()
历史记录看着简单,但置顶逻辑、缓存读写时机、JSON 序列化这三处,几乎每个团队都踩过至少一个坑。尤其在微信小程序里,storage 读写延迟和冷热启动差异会让问题更隐蔽。










