小程序全局变量需手动实现持久化同步,核心是globaldata与storage双写加初始化兜底:登录后立即同步写入storage并更新globaldata,在app.vue的onlaunch/onshow中统一从storage读取并解析挂载,避免数据丢失或覆盖。

小程序端的全局变量不能靠“自动”持久化同步——必须手动设计写入时机、校验逻辑和容错机制,否则必然丢数据或覆盖错。
为什么 uni.setStorageSync 不等于“自动同步”
很多人以为只要在登录后调用 uni.setStorageSync('token', token) 就万事大吉,结果冷启动进首页发现 uni.getStorageSync('token') 是 null。原因很实在:
- 没在
App.vue的onLaunch或onShow里主动读取并挂载到getApp().globalData,导致后续页面读的是空对象 - 用了异步的
uni.setStorage,但没等回调就跳转,实际根本没存成功 - 在分包页面里直接读
getApp().globalData,但主包还没执行初始化逻辑,globalData 还是初始空值 - 存了复杂对象(比如带
Date、RegExp、函数的用户信息),小程序setData序列化失败,静默丢弃
真正可靠的同步链路:globalData + storage 双写 + 初始化兜底
这不是“选一个”,而是三者必须串联。核心动作只有三步,但缺一不可:
- 登录成功后,**立刻**写 storage:
uni.setStorageSync('user', JSON.stringify(userInfo))(注意 stringify) - **同时**更新
getApp().globalData.user = userInfo,确保当前会话内所有页面可读 - 在
App.vue的onLaunch和onShow中,统一执行初始化:const saved = uni.getStorageSync('user')<br>if (saved) {<br> try {<br> getApp().globalData.user = JSON.parse(saved)<br> } catch (e) {<br> // 解析失败就清掉,避免脏数据<br> uni.removeStorageSync('user')<br> }<br>}
哪些数据该存、哪些不该存?看体积和变更频率
storage 是有限资源(微信限制 10MB,实际建议压到 2MB 内),别把它当数据库用:
- ✅ 适合存:
token、userId、theme、lastLoginTime这类小体积、低频更新的只读/弱响应式字段 - ❌ 别存:
userProfile(含头像 base64)、messageList、cacheMap这类可能超 50KB 或频繁增删的对象——改用uni.getFileSystemManager().writeFile存沙箱路径,再把路径字符串存在 storage 里 - ⚠️ 小心存:
Date对象——JSON.stringify(new Date())得到的是字符串,读出来得自己new Date(str)转回,否则后续比较时间会出错
真机调试最容易漏掉的坑
模拟器跑得好好的,一上真机就丢数据,大概率栽在这几个点:
- Android 后台被杀后重启,
onLaunch会触发,但onShow不一定——所以初始化逻辑必须放在onLaunch,不能只靠onShow - iOS 微信下拉刷新会触发新
onShow,但 globalData 是新的空对象,必须再次从 storage 拉一次 - 调用
uni.getStorageSync前没加 try/catch,遇到损坏数据直接报错中断后续流程 - 用了
uni.setStorage(异步)却没处理fail回调,磁盘满或权限拒绝时完全无感知
最常被忽略的一点:globalData 本身不持久,它只是内存里的一个引用;storage 才是唯一落地的载体。所有“同步”动作,本质都是“storage ←→ globalData ←→ 页面使用”的三次搬运,少一次,数据就不闭环。











