Vue Pinia 持久化存储二次封装

什么是 Pinia ?

Pinia 是2019年由vue.js官方成员重新设计的新一代状态管理库,类似Vuex。这里就不过多介绍,具体Pinia使用方法可以参考 Pinia 主页

下面我们一起研究一下基于Pinia开发的持久化存储插件

什么是持久化存储?

简单的说就是浏览器缓存与Store之间相互同步;我们在使用常规的Store存储的时候,会遇到刷新页面状态库就会被重置,这让我们很苦恼;

通常遇到这个问题,我们很容易想到用sessionStorage或者localStorage来存储相应的数据,当存储store变多时,就麻烦了,需要写一堆的废代码,不好阅读也不美观。

有没有更好的办法呢?
pinia-plugin-persist 就很好的解决的这个问题; 但在实际使用中,发现一个不方便的地方,该插件是以模块来存储的,一个store就是一模块,有时候我们需要一个一个字段去存,比如登录我们就只需要存个userInfo字段就行;为了处理类似这种情况在pinia-plugin-persist基础上进行了升级改造。

相关源码

index.d.ts

js 复制代码
interface PersistStrategy {
  key?: string
  storage?: Storage
  paths?: string[]
}
interface PersistOptions {
  enabled: true
  strategies?: PersistStrategy[]
}
declare module 'pinia' {
  interface DefineStoreOptionsBase<S, Store> {
    persist?: PersistOptions
  }
}

export { PersistOptions, PersistStrategy }

pinia-store-persist.ts

js 复制代码
import { PiniaPluginContext } from 'pinia'
import { PersistStrategy } from '../pinia-persist'

type Store = PiniaPluginContext['store']
type PartialState = Partial<Store['$state']>

// 更新本地缓存
export const updateStorage = (strategy: PersistStrategy, store: Store) => {
  const storage = strategy?.storage || sessionStorage
  const paths = strategy?.paths || []
  if (strategy.key) {
    // 判断是否按照模块缓存
    const state = paths.reduce((obj, key) => {
      obj[key] = store.$state[key]
      return obj
    }, {} as PartialState)
    storage.setItem(strategy.key, JSON.stringify(state))
  } else {
    // 单个缓存
    paths.forEach((key) => {
      const state = store.$state[key]
      storage.setItem(key, JSON.stringify(state))
    })
  }
}

export default ({ options, store }: PiniaPluginContext): void => {
  // 判断插件功能是否开启
  if (options.persist?.enabled) {
    // 默认策略实例
    const defaultStrategy = [
      {
        key: store.$id,
        storage: sessionStorage,
        paths: []
      }
    ]

    const strategies = options.persist?.strategies?.length ? options.persist?.strategies : defaultStrategy

    strategies.forEach((strategy) => {
      const storage = strategy?.storage || sessionStorage
      const paths = strategy?.paths || []
      if (strategy.key) {
        const result = storage.getItem(strategy.key)
        result && store.$patch(JSON.parse(result))
      } else {
        paths.forEach((key) => {
          const result = storage.getItem(key)
          if (result) {
            const obj: { [key: string]: any } = {}
            obj[key] = JSON.parse(result)
            // 同步更新store数据
            store.$patch(obj)
          }
        })
      }
    })

    // 监听state变化,同步更新storage
    store.$subscribe(() => {
      strategies.forEach((strategy) => {
        updateStorage(strategy, store)
      })
    })
  }
}

引入

store/index.ts

js 复制代码
import { createPinia } from 'pinia'
import piniaStorePersist from '@/plugins/pinia-persist/pinia-store-persist'

const store = createPinia().use(piniaStorePersist)

export default store

使用

js 复制代码
export const CommonStore = defineStore('common', {
  //...
  persist: {
    enabled: true,
    strategies: [
      {
        storage: localStorage,
        paths: ['userInfo']
      }
    ]
  }
})

最后

如果本文对您有什么帮助,别忘了动动手指点个赞❤️。 本文如果有错误和不足之处,欢迎大家在评论区指出,多多提出您宝贵的意见!

相关推荐
计算机-秋大田5 小时前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
禾苗种树6 小时前
在 Vue 3 中使用 ECharts 制作多 Y 轴折线图时,若希望 **Y 轴颜色自动匹配折线颜色**且无需手动干预,可以通过以下步骤实现:
前端·vue.js·echarts
小盼江7 小时前
水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 代码+开发文档+视频教程
vue.js·spring boot·ui
初遇你时动了情8 小时前
react module.scss 避免全局冲突类似vue中scoped
vue.js·react.js·scss
烂蜻蜓9 小时前
Uniapp 设计思路全分享
前端·css·vue.js·uni-app·html
bin91539 小时前
DeepSeek 助力 Vue 开发:打造丝滑的二维码生成(QR Code)
前端·javascript·vue.js·ecmascript·deepseek
浪九天14 小时前
Vue 不同大版本与 Node.js 版本匹配的详细参数
前端·vue.js·node.js
尚学教辅学习资料14 小时前
基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考
vue.js·spring boot·uni-app·旅游
IT、木易15 小时前
跟着AI学vue第五章
前端·javascript·vue.js
薛定谔的猫-菜鸟程序员15 小时前
Vue 2全屏滚动动画实战:结合fullpage-vue与animate.css打造炫酷H5页面
前端·css·vue.js