uni.setStorageSync存搜索历史需先读再处理:去重用Array.from(new Set([...old, newWord])),限数量如.slice(0, 10),空值判断history = uni.getStorageSync('searchHistory') || [],注意v-model变量名一致及安卓光标聚焦。

uni-app 里怎么用 uni.setStorageSync 存搜索历史
存历史记录本身不难,关键是别直接覆盖、别存重复、别超量。默认用 uni.setStorageSync 写入数组,但每次都要先读出来再处理,否则新词一来就把旧的全冲掉了。
常见错误是:用户搜“苹果”又搜“苹果”,结果数组里出现两个“苹果”;或者存了 50 条,滚动列表卡得像 PPT。
- 每次写入前用
uni.getStorageSync拿出已有数组,用Array.from(new Set([...old, newWord]))去重(注意:Set对字符串安全,对对象不行) - 限制数量,比如最多存 10 条:
history = [newWord, ...oldHistory].slice(0, 10) - 别在
onLoad或onShow里反复读写——只在用户真正提交搜索后才触发存操作
词云布局用 view + 动态 style 就够了,别上 canvas
uni-app 没有原生词云组件,也别费劲引入第三方 canvas 库——性能差、真机容易错位、H5 和小程序表现还不一致。用纯 CSS 布局 + 字体大小/颜色随机化,效果够用,且稳定。
核心是让每个词独立控制字号和颜色,靠 flex 流式排列,自动换行。
- 给每个
view加:style="{ fontSize: size + 'px', color: color }",其中size可按词频或简单用Math.random() * 20 + 12 - 外层容器设
display: flex; flex-wrap: wrap; justify-content: center; - 避免用
position: absolute模拟词云位置——无法响应式,也不利于可访问性
点击历史词触发搜索时,为什么 input 组件没更新?
因为 uni-app 的 input 是受控组件,光改 value 数据不行,还得确保 v-model 绑定的变量确实被赋值,且页面没意外触发 onPullDownRefresh 或 onBackPress 导致 data 重置。
最常踩的坑是:点历史词后调了 this.searchValue = word,但 input 上写的是 v-model="searchText",变量名对不上。
- 检查
v-model绑定的变量名和你赋值的变量是否完全一致(大小写、拼写) - 如果用了防抖搜索,在点击历史词后建议手动清掉 pending 定时器:
clearTimeout(this.timer) - 安卓真机上偶尔 input 光标不聚焦,可以加一句
this.$nextTick(() => this.$refs.inputRef?.focus())
本地存储的兼容性陷阱:uni.getStorageInfoSync 不是万能探针
你以为用 uni.getStorageInfoSync 能查出 key 是否存在?其实它只返回总容量和已用条数,不告诉你某个 key 存不存在。直接 uni.getStorageSync('searchHistory') 返回 null 才是真实信号。
更隐蔽的问题是:App 端(尤其是 iOS)在升级后可能清空 uni.setStorageSync 数据,而 H5 端走的是 localStorage,路径隔离。别假设所有平台行为一致。
- 读取时必须做空值判断:
const history = uni.getStorageSync('searchHistory') || [] - 不要依赖
uni.getStorageInfoSync().keys判断 key 存在——这个字段在某些低版本微信小程序里压根不存在 - 如需跨端持久化更强,考虑加一层兜底:H5 用
localStorage,App 用uni.setStorage(异步版),但日常小需求,同步版够用
实际最难的不是布局或存储,是让用户觉得“这个词怎么又出现了”——去重逻辑漏了空格、大小写、URL 编码差异,比如“微信”和“微信%20”会被当两个词。这种细节,调试时得拿真机日志一条条看存进去的是啥。


















