小程序到底用Store还是LocalStorage ?

很多开发者刚开始都会觉得"既然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里反复读:

    javascript 复制代码
    onShow() {
      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管理的是内存数据 (存在小程序的内存里)。

比如你做"切换账号"功能,需要同时更新:tokenuserInfoisLoginaudienceUserId4个状态:

  • 用localStorage:得写4次wx.setStorageSync(4次磁盘写入),读的时候得4次wx.getStorageSync(4次磁盘读取),磁盘操作比内存慢100倍以上,频繁操作会有卡顿感。
  • 用store:直接操作内存里的globalData,1次store.set就能更新关联状态,读写几乎无延迟------这对小程序的流畅度很重要。

3. 「只能存字符串」------复杂状态会出问题

localStorage只能存字符串,存对象/数字/布尔值都得手动JSON.stringifyJSON.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------它帮你省掉了"手动监听、反复读盘、处理序列化"这些脏活累活,让代码更简洁、不易出错。
相关推荐
一只小风华~5 小时前
学习笔记:Vue Router 中的链接匹配机制与样式控制
前端·javascript·vue.js·笔记·学习·ecmascript
uhakadotcom5 小时前
在chrome浏览器插件之中,options.html和options.js常用来做什么事情
前端·javascript·面试
西瓜树枝5 小时前
Chrome 扩展开发从入门到实践:以 Cookie 跨页提取工具为例,拆解核心模块与交互逻辑
前端·javascript·chrome
冰糖雪梨dd5 小时前
JS中new的过程发生了什么
开发语言·javascript·原型模式
小帆聊前端6 小时前
Lodash 深度解读:前端数据处理的效率利器,从用法到原理全拆解
前端·javascript
一枚前端小能手6 小时前
🔍 那些不为人知但是好用的JS小秘密
前端·javascript
北城以北88887 小时前
Vue-- Axios 交互(二)
javascript·vue.js·交互
Zuckjet_7 小时前
第 7 篇:交互的乐趣 - 响应用户输入
前端·javascript·webgl
通往曙光的路上7 小时前
day7_vite 啊哈哈啊哈哈哈哈哈
javascript