globalData 是运行时内存对象,不持久、不跨 WebView、不自动同步;需手动桥接 uni.setStorageSync 实现伪实时同步,关键节点须双写更新。

小程序端 globalData 不能实时持久化,别硬凑
globalData 本质是运行时内存对象,关掉小程序进程就清空,它不存本地、不跨 WebView、也不自动同步。所谓“实时持久化同步”在小程序端本身就是矛盾需求——globalData 和 uni.setStorageSync 是两套机制,混用必须手动桥接,否则 token 更新了页面还读着旧值。
常见错误现象:
- 登录后更新了
globalData.token,但 API 请求头仍发旧 token - 分包页面里调用
getApp().globalData拿到的是初始化时的空值 - 小程序冷启动后,
globalData回退成默认值,但本地存储里明明有有效 token
用 getStorageSync + getApp().globalData 做双写桥接
真正可行的“伪实时同步”,是在关键节点手动把持久化数据载入 globalData,并确保所有写操作都同时触达两者。
正确做法:
- 在
App.vue的onLaunch和onShow中,统一从uni.getStorageSync('token')读取并赋值给getApp().globalData.token - 每次登录成功或 token 刷新后,必须同步执行:
uni.setStorageSync('token', newToken)和getApp().globalData.token = newToken - 不要在组件里直接解构
globalData后赋值(const { token } = app.globalData; token = 'xxx'无效) - 若使用 TypeScript,建议在
App.vue上加 JSDoc 注释,明确globalData类型,避免属性访问报错
Vuex / Pinia 需要额外处理持久化和小程序兼容
如果你用了 Pi nia 或 Vuex 管理状态,它默认只存在内存中,小程序冷启动后 store 就空了。必须用插件桥接到 uni.setStorageSync。
关键点:
-
pinia-plugin-persistedstate默认用localStorage,小程序端必须重写storage配置项,换成uni.setStorageSync和uni.getStorageSync - store 的 state 里不能放函数、正则、Date 实例等不可序列化值,否则小程序 setData 会失败或白屏
- Pinia 的
persist配置需显式指定key,避免多模块 key 冲突(如用户模块用'user-store',而非默认的'pinia') - H5 和小程序行为不一致:H5 可能自动恢复,小程序必须等
onLaunch后 store 才完成初始化,页面里访问 store.state 前要加空值判断
哪些场景真该放弃“全局变量”思路
当你要的不是“共享一个值”,而是“任意时刻都能拿到最新且一致的状态”,globalData + 手动双写已经逼近维护极限。这时候该换思路:
- 高频变动的数据(比如购物车实时数量、未读消息数)——改用事件总线(
uni.$emit/uni.$on)或封装请求拦截器自动注入 token - 需要响应式更新的 UI 状态(比如主题色切换)——用 Pinia + computed 包一层,再配合
watch同步写入uni.setStorageSync - 跨分包、跨 WebView 的强一致性要求——小程序原生不支持,只能靠服务端兜底(如用 openid + 时间戳生成临时凭证),前端不做强同步假设
最易被忽略的一点:globalData 在微信小程序的多个 WebView(比如从公众号跳转进来的页面)之间完全隔离,你写的“同步逻辑”在那种场景下根本不会执行。别等上线后才发现分享链接里的页面拿不到登录态。


















