Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态
在某些特定的单页面应用场景下,我们使用常规的 store 来存储数据,很多时候面临着刷新就会被重置,所以,我们急需 pinia-plugin-persist 来实现对某些特定的数据进行状态保持
npm i pinia-plugin-persist
Vue3 main.ts- 配置
import {
createApp } from 'vue'
import {
createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
const pinia = createPinia()
pinia.use(piniaPersist)
createApp({
})
.use(pinia)
.mount('#app')
Typescript definitions tsconfig.json - 配置
{
"compilerOptions": {
"types": [
"pinia-plugin-persist"
]
},
}
/store/index.js - 定义
export const useUserStore = defineStore('storeUser', {
state () {
return {
firstName: 'S',
lastName: 'L',
accessToken: 'xxxxxxxxxxxxx',
}
},
persist: {
enabled: true,
strategies: [
{
key: 'accessToken', //自定义 Key值
storage: localStorage, // 选择存储方式
paths: ['accessToken'] // state 中的字段名,按组打包储存
// assessToken,数据不为空时localStorage才会去存储,数据为空时,不会去存储()
},
],
},
})
使用
<template>
<button @click="onButton">点击增加</button>
</template>
<script lang="ts" setup>
import store from '@/store'
const appStore = store.useUserStore()
// computed 可以获取响应式数据
const assessToken = computed(() => {
appStore.accessToken })
const onButton = () => {
console.log(assessToken)
}
</script>
<style lang="scss" scoped></style>
源码解读
type Store = PiniaPluginContext['store'];
type PartialState = Partial<Store['$state']>;
export const updateStorage = (strategy: PersistStrategy, store: Store) => {
// 默认使用 sessionStorage
const storage = strategy.storage || sessionStorage
// 默认存储 key 为 store.$id
const storeKey = strategy.key || store.$id
if (strategy.paths) {
// 遍历 paths 将对应的属性收集到 finalObj 中
const partialState = strategy.paths.reduce((finalObj, key) => {
finalObj[key] = store.$state[key]
return finalObj
}, {
} as PartialState)
// 执行存储
storage.setItem(storeKey, JSON.stringify(partialState))
} else {
// 如果没有 paths,则按整个 store.$state 存储
storage.setItem(storeKey, JSON.stringify(store.$state))
}
}
export default ({
options, store }: PiniaPluginContext): void => {
// 判断插件功能是否开启
if (options.persist?.enabled) {
// 默认策略实例
const defaultStrat: PersistStrategy[] = [{
key: store.$id,
storage: sessionStorage,
}]
const strategies = options.persist?.strategies?.length ? options.persist?.strategies : defaultStrat
strategies.forEach((strategy) => {
const storage = strategy.storage || sessionStorage
const storeKey = strategy.key || store.$id
const storageResult = storage.getItem(storeKey)
if (storageResult) {
// 如果 storage 中存在同步数据
store.$patch(JSON.parse(storageResult))
updateStorage(strategy, store)
}
})
store.$subscribe(() => {
// 监听 state 变化,同步更新 storage
strategies.forEach((strategy) => {
updateStorage(strategy, store)
})
})
}
}