Pinia 的状态存储在内存中。当你刷新页面时,浏览器会重新加载页面,导致 JavaScript 环境重新初始化,这意味着存储在内存中的数据会丢失。因为刷新操作会重新加载整个应用程序,包括重新创建 Vue 实例和 Pinia 实例,而原来存储在 Pinia store 中的数据是存储在之前的 JavaScript 运行时环境中的,一旦刷新,之前的环境被清除,数据也就消失了。
Pinia 本身并不会自动将数据持久化到本地存储(如 localStorage 或 sessionStorage)或其他持久化存储介质中。如果没有使用持久化存储,那么存储在 Pinia 中的数据就只是临时存储在内存中,仅在当前页面会话期间有效。
可以使用 pinia-plugin-persist 插件
npm install pinia-plugin-persist -D
在store/index.ts
文件中
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPersist)
import { defineStore } from 'pinia';
const useMyStore = defineStore('myStore', {
state: () => ({
count: 0
}),
persist: {
enabled: true
// 其他配置可以去pinia-plugin-persist文档查看,https://seb-l.github.io/pinia-plugin-persist/advanced/strategies.html
}
});
index.ts
import { PiniaPluginContext } from 'pinia'
export interface PersistStrategy {
key?: string;
storage?: Storage;
paths?: string[];
}
export interface PersistOptions {
enabled: true;
strategies?: PersistStrategy[];
}
type Store = PiniaPluginContext['store'];
type PartialState = Partial<Store['$state']>;
declare module 'pinia' {
export interface DefineStoreOptionsBase<S, Store> {
persist?: PersistOptions;
}
}
export const updateStorage = (strategy: PersistStrategy, store: Store) => {
const storage = strategy.storage || sessionStorage
const storeKey = strategy.key || store.$id
if (strategy.paths) {
const partialState = strategy.paths.reduce((finalObj, key) => {
finalObj[key] = store.$state[key]
return finalObj
}, {} as PartialState)
storage.setItem(storeKey, JSON.stringify(partialState))
} else {
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) {
store.$patch(JSON.parse(storageResult))
updateStorage(strategy, store)
}
})
store.$subscribe(() => {
strategies.forEach((strategy) => {
updateStorage(strategy, store)
})
})
}
}
import { PiniaPluginContext } from 'pinia'
export interface PersistStrategy {
key?: string;
storage?: Storage;
paths?: string[];
}
export interface PersistOptions {
enabled: true;
strategies?: PersistStrategy[];
}
type Store = PiniaPluginContext['store'];
type PartialState = Partial<Store['$state']>;
PiniaPluginContext
:从 pinia
库中导入 PiniaPluginContext
,它包含了 Pinia 插件执行时所需的上下文信息,如 store
、options
等。PersistStrategy
接口:定义了持久化策略的类型。
key
:可选属性,用于指定存储在 Storage
中的键名,默认为 store
的 $id
。storage
:可选属性,指定存储的位置,类型为 Storage
,可以是 localStorage
或 sessionStorage
等,默认为 sessionStorage
。paths
:可选属性,是一个字符串数组,用于指定只持久化 store
状态中的部分属性。PersistOptions
接口:定义了持久化的配置选项。
enabled
:必须为 true
,表示开启持久化功能。strategies
:可选属性,是一个 PersistStrategy
数组,可指定多个持久化策略。Store
:从 PiniaPluginContext
中提取 store
的类型。PartialState
:表示 store
状态的部分属性,是 Store['$state']
的 Partial
类型。declare module 'pinia' {
export interface DefineStoreOptionsBase<S, Store> {
persist?: PersistOptions;
}
}
通过 declare module
语法扩展 pinia
库中的 DefineStoreOptionsBase
接口,添加了一个可选的 persist
属性,类型为 PersistOptions
。这样,在定义 Pinia store 时,就可以使用 persist
选项来配置持久化功能。
updateStorage
函数export const updateStorage = (strategy: PersistStrategy, store: Store) => {
const storage = strategy.storage || sessionStorage
const storeKey = strategy.key || store.$id
if (strategy.paths) {
const partialState = strategy.paths.reduce((finalObj, key) => {
finalObj[key] = store.$state[key]
return finalObj
}, {} as PartialState)
storage.setItem(storeKey, JSON.stringify(partialState))
} else {
storage.setItem(storeKey, JSON.stringify(store.$state))
}
}
store
的状态存储到指定的 Storage
中。strategy
:持久化策略对象,包含存储的键名、存储位置和要持久化的属性路径等信息。store
:Pinia store 实例。strategy
中的 storage
属性获取存储位置,若未指定则使用 sessionStorage
;根据 strategy
中的 key
属性获取存储键名,若未指定则使用 store
的 $id
。strategy
中指定了 paths
,则只提取 store
状态中 paths
所包含的属性,将其存储到 partialState
对象中,然后将 partialState
序列化为 JSON 字符串并存储到 Storage
中。paths
,则将整个 store
状态序列化为 JSON 字符串并存储到 Storage
中。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) {
store.$patch(JSON.parse(storageResult))
updateStorage(strategy, store)
}
})
store.$subscribe(() => {
strategies.forEach((strategy) => {
updateStorage(strategy, store)
})
})
}
}
PiniaPluginContext
对象,包含 options
(store 的配置选项)和 store
(Pinia store 实例)。options.persist
是否存在且 enabled
为 true
,若不满足则不执行持久化操作。defaultStrat
,使用 store
的 $id
作为键名,sessionStorage
作为存储位置。options.persist.strategies
是否存在来确定最终使用的持久化策略数组 strategies
,若不存在则使用默认策略。strategies
数组,对于每个策略:
Storage
中获取存储的状态信息。store.$patch
方法将存储的状态应用到 store
中,并调用 updateStorage
函数更新存储。store.$subscribe
方法监听 store
的状态变化,当状态发生变化时,遍历 strategies
数组,调用 updateStorage
函数将最新状态存储到 Storage
中。这段代码实现了一个 Pinia 插件,用于将 Pinia store 的状态持久化到 Storage
中。它支持多种持久化策略,可以指定存储的键名、存储位置和要持久化的属性路径。在应用启动时,会尝试从 Storage
中恢复状态;在状态发生变化时,会自动更新存储。