很多开发者刚开始都会觉得"既然localStorage能存公共数据,为啥还要store?",但其实两者解决的是完全不同的问题 :localStorage是"持久化存储工具 ",而store是"内存状态管理工具",看似都能存数据,实则在"实时同步""效率""状态关联"上差了关键一步,绝非"脱裤子放屁"。
一、先戳localStorage的3个"硬伤"------你用它管理实时状态会踩的坑
假设你把Token、isLogin存在localStorage里,想实现"登录后所有页面立刻更新登录按钮(显示'退出')",会发现根本做不到或很麻烦:
1. 「改了数据,其他页面不会主动通知」------实时同步失效
localStorage是"被动存储",它没有"发布订阅"能力:
比如A页面登录成功,存了Token到localStorage:
javascript
// A页面:登录成功
wx.setStorageSync('token', 'xxx123');
wx.setStorageSync('isLogin', true);
但B页面此时已经打开(比如Tab页),它不会知道localStorage变了,登录按钮还是显示"登录",必须手动做以下操作之一:
-
方案1:每次页面显示都读localStorage (冗余且不实时)
B页面得在
onShow
里反复读:javascriptonShow() { const isLogin = wx.getStorageSync('isLogin'); this.setData({ isLogin }); // 每次切到B页面才更新,不切就不更 }
如果B页面是个长列表页,频繁切页会反复读磁盘,影响性能。
-
方案2:自己写监听逻辑 (复杂且容易漏)
得用小程序的
wx.onStorageChange
监听localStorage变化,但这玩意儿有坑:javascript// B页面:监听localStorage变化 onLoad() { this.storageListener = wx.onStorageChange((res) => { if (res.key === 'isLogin') { this.setData({ isLogin: res.newValue }); } }); } onUnload() { // 必须手动销毁监听,否则内存泄漏 this.storageListener(); }
每个需要同步的页面都得写这段代码,3个页面就写3遍,还容易忘销毁监听。
而store的核心优势就是"自动通知" :只要配置了storeWatch
,A页面改了isLogin
,B/C/D页面会立刻收到通知并更新,不用写任何监听代码------这正是你说的"一个地方改,其他地方立刻响应"。
2. 「读写效率低」------频繁操作会卡顿
localStorage是磁盘存储 (存在手机本地文件里),而store管理的是内存数据 (存在小程序的内存里)。
比如你做"切换账号"功能,需要同时更新:token
、userInfo
、isLogin
、audienceUserId
4个状态:
- 用localStorage:得写4次
wx.setStorageSync
(4次磁盘写入),读的时候得4次wx.getStorageSync
(4次磁盘读取),磁盘操作比内存慢100倍以上,频繁操作会有卡顿感。 - 用store:直接操作内存里的
globalData
,1次store.set
就能更新关联状态,读写几乎无延迟------这对小程序的流畅度很重要。
3. 「只能存字符串」------复杂状态会出问题
localStorage只能存字符串,存对象/数字/布尔值都得手动JSON.stringify
和JSON.parse
,容易踩坑:
javascript
// 存用户信息(对象),必须转字符串
const userInfo = { name: '张三', age: 20 };
wx.setStorageSync('userInfo', JSON.stringify(userInfo));
// 取的时候转回来
const userInfo = JSON.parse(wx.getStorageSync('userInfo'));
// 坑1:如果数据里有函数/循环引用,JSON.stringify会报错
// 坑2:如果localStorage被清空,JSON.parse会报"Unexpected token u in JSON at position 0"
而store可以直接存任意类型 :对象、数组、数字、布尔值,不用处理序列化,也不会有解析错误------比如你存userInfo
对象,store.set('userInfo', userInfo)
直接存,store.get('userInfo')
直接取,省心。
二、store和localStorage不是"二选一",而是"配合用"
实际项目里,store和localStorage是互补关系,不是互斥的:
-
store管"实时状态" :比如
isLogin
(登录状态)、currentPage
(当前页面)、popupShow
(弹窗显示状态)------这些需要实时同步、频繁读写的状态,用store管理,保证实时性和效率。 -
localStorage管"持久化" :比如
token
(登录凭证)、userInfo
(用户信息)------这些需要重启小程序后不丢失的状态,在store更新时同步存到localStorage,在小程序启动时从localStorage读回store:javascript// store.js:小程序启动时,从localStorage加载持久化数据 createApp(options) { options.onLaunch = function () { // 从localStorage读token和userInfo,初始化到store const token = wx.getStorageSync('token') || ''; const userInfo = wx.getStorageSync('userInfo') ? JSON.parse(wx.getStorageSync('userInfo')) : {}; this.globalData = { token, userInfo, isLogin: !!token }; store.app = this; }; return options; } // 登录时,store更新同时同步到localStorage loginSuccess(token, userInfo) { store.set('token', token); store.set('userInfo', userInfo); store.set('isLogin', true); // 同步持久化 wx.setStorageSync('token', token); wx.setStorageSync('userInfo', JSON.stringify(userInfo)); }
这样既解决了"实时同步"(store的活),又解决了"重启不丢数据"(localStorage的活)------这才是完整的解决方案。
三、总结:不是"脱裤子放屁",而是"解决痛点"
- 如果你只需要"存个数据,重启不丢"(比如Token),且不用实时同步(改了之后用户切页面才看得到),那localStorage够用,store确实没必要。
- 但如果你需要"改了数据,所有页面立刻响应"(比如登录后立刻显示用户头像、退出后立刻隐藏会员按钮),或需要管理"关联状态"(改Token的同时要改isLogin、清空过期时间),那localStorage根本搞不定,必须用store------它帮你省掉了"手动监听、反复读盘、处理序列化"这些脏活累活,让代码更简洁、不易出错。