pinia-plugin-persistedstate详解与Vue3使用示例

文章目录

    • 一、核心原理
    • 二、核心配置项(完整)
    • [三、Vue3 完整使用步骤](#三、Vue3 完整使用步骤)
      • [1. 安装依赖](#1. 安装依赖)
      • [2. 全局注册插件(main.ts/main.js)](#2. 全局注册插件(main.ts/main.js))
      • [3. Store 中启用持久化(两种风格)](#3. Store 中启用持久化(两种风格))
        • [(1)Option Store 风格(选项式)](#(1)Option Store 风格(选项式))
        • [(2)Setup Store 风格(组合式,推荐 Vue3)](#(2)Setup Store 风格(组合式,推荐 Vue3))
      • [4. 多策略持久化(进阶)](#4. 多策略持久化(进阶))
      • [5. 组件中使用](#5. 组件中使用)
    • 四、常见场景与最佳实践
    • 五、常见问题

pinia-plugin-persistedstate 是 Pinia 官方生态中最主流的状态持久化插件 ,核心作用是将 Pinia 的状态自动同步到本地存储(如 localStorage/sessionStorage),页面刷新后状态不丢失,解决内存状态易重置的痛点。它配置极简、支持细粒度控制、兼容 Vue3 与 Pinia 全版本,是 Vue3 项目状态持久化的首选方案。


一、核心原理

  • 插件通过 Pinia 的插件机制 全局注册,监听所有 Store 的状态变更。
  • 状态更新时,自动序列化并写入指定存储介质(默认 localStorage)。
  • 页面初始化时,自动反序列化读取存储数据,覆盖到对应 Store 的 state。
  • 支持全局配置 + 单个 Store 配置,优先级:Store 配置 > 全局配置。

二、核心配置项(完整)

persist 支持布尔值(简单开启)或对象(精细配置),完整配置如下:

配置项 类型 默认值 说明
enabled boolean true 是否启用持久化
key string Store ID 存储在 localStorage 中的键名(建议自定义避免冲突)
storage Storage localStorage 存储介质:localStorage/sessionStorage/自定义存储
paths string[] undefined 仅持久化指定字段(路径数组,如 ['user.token', 'theme']
serializer object JSON 自定义序列化/反序列化:{ serialize, deserialize }
beforeRestore () => void - 状态恢复前钩子
afterRestore () => void - 状态恢复后钩子
strategies array - 多策略配置(不同字段用不同存储)

三、Vue3 完整使用步骤

1. 安装依赖

bash 复制代码
# npm
npm install pinia pinia-plugin-persistedstate

# yarn
yarn add pinia pinia-plugin-persistedstate

# pnpm
pnpm add pinia pinia-plugin-persistedstate

2. 全局注册插件(main.ts/main.js)

typescript 复制代码
import { createApp } from 'vue'
import { createPinia } from 'pinia'
// 引入持久化插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()

// 注册插件(全局生效)
pinia.use(piniaPluginPersistedstate)

app.use(pinia)
app.mount('#app')

3. Store 中启用持久化(两种风格)

(1)Option Store 风格(选项式)

最简用法(全部字段持久化到 localStorage)

typescript 复制代码
// src/stores/counter.ts
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    isLoading: false
  }),
  actions: {
    increment() {
      this.count++
    }
  },
  // ✅ 开启持久化(默认配置)
  persist: true
})

精细配置(推荐生产环境)

typescript 复制代码
// src/stores/user.ts
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    token: '',
    userInfo: {
      id: '',
      name: '',
      avatar: ''
    },
    tempData: null // 不需要持久化
  }),
  actions: {
    setToken(token: string) {
      this.token = token
    },
    logout() {
      this.token = ''
      this.userInfo = { id: '', name: '', avatar: '' }
      // 清除本地存储
      localStorage.removeItem('app-user-store')
    }
  },
  // ✅ 自定义持久化配置
  persist: {
    key: 'app-user-store', // 自定义存储键
    storage: localStorage, // 存储介质
    paths: ['token', 'userInfo'], // 仅持久化指定字段
    // 自定义序列化(处理 Date 等特殊类型)
    serializer: {
      serialize: (value) => JSON.stringify(value),
      deserialize: (value) => JSON.parse(value)
    },
    // 恢复钩子
    afterRestore: (ctx) => {
      console.log('用户状态已恢复', ctx.store.$state)
    }
  }
})
(2)Setup Store 风格(组合式,推荐 Vue3)
typescript 复制代码
// src/stores/setting.ts
import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'

export const useSettingStore = defineStore('setting', () => {
  // 状态
  const theme = ref('light')
  const language = ref('zh-CN')
  const collapsed = ref(false)

  // 动作
  const setTheme = (val: string) => {
    theme.value = val
  }

  // ✅ 持久化配置(第三个参数)
  return { theme, language, collapsed, setTheme }
}, {
  persist: {
    key: 'app-setting',
    storage: sessionStorage, // 会话存储(关闭标签页清空)
    paths: ['theme', 'language'] // 不持久化 collapsed
  }
})

4. 多策略持久化(进阶)

不同字段使用不同存储介质:

typescript 复制代码
persist: {
  strategies: [
    // token 长期保存到 localStorage
    { key: 'auth-token', storage: localStorage, paths: ['token'] },
    // 主题仅会话保存到 sessionStorage
    { key: 'ui-theme', storage: sessionStorage, paths: ['theme'] }
  ]
}

5. 组件中使用

vue 复制代码
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia' // 保持解构响应式

const counterStore = useCounterStore()
const userStore = useUserStore()

// 解构状态(必须用 storeToRefs)
const { count } = storeToRefs(counterStore)
const { token, userInfo } = storeToRefs(userStore)

// 调用方法
const add = () => counterStore.increment()
</script>

<template>
  <div>
    <h2>计数:{{ count }}</h2>
    <button @click="add">+1</button>

    <div v-if="token">
      <p>用户名:{{ userInfo.name }}</p>
      <button @click="userStore.logout">退出登录</button>
    </div>
    <div v-else>未登录</div>
  </div>
</template>

四、常见场景与最佳实践

  1. 只持久化必要字段 :用 paths 过滤,减少存储体积。
  2. 敏感信息处理:token 等可持久化,临时数据不要持久化。
  3. 存储介质选择
    • localStorage:长期保存(关闭浏览器仍在)
    • sessionStorage:会话保存(标签页关闭即清空)
  4. 清除持久化 :登出时用 localStorage.removeItem(key)store.$reset()
  5. TypeScript 支持:完美兼容,无需额外配置。

五、常见问题

  • 刷新后状态仍丢失 :检查 persist 是否开启、paths 路径是否正确、存储键是否冲突。
  • 特殊类型(Date/RegExp)无法存储 :自定义 serializer 序列化。
  • SSR 兼容 :需判断环境,避免服务端访问 window 对象。
相关推荐
方便面不加香菜2 小时前
C++ 类和对象(二)
开发语言·c++
@大迁世界2 小时前
20.“可复用组件”具体指的是什么?如何设计与产出这类组件?.
开发语言·前端·javascript·ecmascript
有味道的男人2 小时前
电商效率翻倍:用 Open Claw 对接 1688 接口,快速实现图片选品 + 货源监控
java·开发语言·数据库
froginwe112 小时前
Chart.js 雷达图:深入解析与实际应用
开发语言
枫叶丹42 小时前
【HarmonyOS 6.0】屏幕管理新特性:多屏坐标转换详解
开发语言·华为·harmonyos
Dxy12393102162 小时前
Python有哪些方法可以进行文本纠错
开发语言·python
fengci.2 小时前
php反序列化(复习)(第四章)
android·开发语言·学习·php·android studio
Jasmine_llq2 小时前
《B3923 [GESP202312 二级] 小杨做题》
开发语言·状态标记算法·顺序输入输出算法·递推迭代算法·循环遍历算法·条件终止算法·累加求和算法