正确做法是先读取历史数组,去重并置顶新关键词,截断至10条后一次性用uni.setStorageSync写入;keyword须为非空字符串,存取key严格统一为小写下划线格式,读取后必须校验Array.isArray以防序列化异常。

搜索历史怎么存进 uni.setStorageSync 才不丢数据
直接用 uni.setStorageSync 存数组没问题,但必须保证每次写入都是「完整覆盖」,不能 push 后再 set —— 因为缓存里没有“读-改-写”原子操作,中间任何一步出错(比如读失败、push 异常)都会导致历史清空或重复。
正确做法是:先读,再去重+截断,最后一次性写入。示例逻辑:
const saveSearchHistory = (keyword) => {
const history = uni.getStorageSync('search_history') || []
// 去重:新词放最前,旧的同名词移除
const filtered = history.filter(item => item !== keyword)
const newHistory = [keyword, ...filtered].slice(0, 10) // 最多存10条
uni.setStorageSync('search_history', newHistory)
}
-
keyword必须是字符串,非空且 trim 后长度 > 0,否则跳过存储 - 不要在
onLoad或页面初始化时就调用读取,应在用户点击搜索框或触发搜索动作后再读——减少无意义 I/O - 安卓低端机上
uni.getStorageSync可能抛错,建议包一层 try/catch 并 fallback 到空数组
为什么 uni.removeStorageSync('search_history') 有时删不掉
不是删除失败,而是你删的是错的 key —— 比如存的时候用了带空格的 key:'search_history ',或者大小写不一致:'Search_History'。本地缓存 key 是严格区分大小写和空白字符的。
更隐蔽的问题是:H5 端实际走的是 localStorage,而小程序端走的是独立沙箱。如果你在 H5 调试时清了浏览器 localStorage,但没在微信开发者工具里清缓存,就会误判“删不掉”。
- 删之前先 console.log 出当前所有 key(可用
Object.keys(uni.getStorageInfoSync().keys),注意 H5 不支持该 API,需降级处理) - 统一用小写 + 下划线命名,例如固定用
'search_history',别用驼峰或中横线 - 清除操作建议封装成函数,并在调用后立即读一次验证是否为空数组
搜索历史列表渲染时,v-for 怎么避免重复 key 报错
如果历史记录里有相同关键词多次出现(比如用户连续搜了两次“苹果”),直接用 item 作 :key 就会触发 Vue 警告:“Duplicate keys”。这不是 uni-app 特有,是 Vue 的渲染机制限制。
解决方式不是加索引,而是生成唯一标识。最稳妥的是用关键词 + 时间戳哈希(简单起见可用 keyword + '_' + Date.now()),但更推荐用「首次出现顺序」来稳定标识:
<view v-for="(item, index) in history" :key="index">
{{ item }}
</view>
- 只要
history数组本身是稳定更新的(即每次 setStorage 都是完整数组),用:key="index"安全且高效 - 千万别用
:key="item",除非你能 100% 保证关键词绝对不重复 - H5 端若开启
vue.config.js中的productionSourceMap: false,控制台可能不报 key 警告,但仍影响 diff 效率
App 和小程序端缓存行为不一致怎么办
根本差异在于:微信小程序的 uni.setStorageSync 是同步写磁盘,而 App(尤其是 iOS)底层用的是 SQLite,存在写入延迟;H5 则完全依赖 localStorage,且部分 iOS Safari 在无用户交互时禁止写入。
这意味着:你在 App 端调用 setStorageSync 后立刻读,偶尔会读到旧值;H5 端在某些 WebView 场景下甚至会静默失败。
- 对一致性要求高的场景(比如搜索后立即展示最新历史),写完后加一次
uni.getStorageSync校验,不一致则重试 1 次(最多) - 不要依赖“写完就一定能读到”,UI 层应以本次操作的
newHistory数组为准做临时渲染,再异步刷新缓存状态 - 上线前务必在真机测试:iOS 微信、Android 微信、App(iOS/Android)、H5(Chrome + Safari)各跑一遍存/读/删流程
缓存不是数据库,它只保证“尽力而为”。真正容易被忽略的,是不同平台对“空字符串”“null”“undefined”的序列化表现不一致 —— 有些会转成 "null" 字符串存进去,下次读出来就不是数组了。每次读取后务必做 Array.isArray(history) 校验,否则后续 v-for 直接报错。











