需要自定义序列化器,因为默认 JSON 序列化会丢失 Date、Map、Set、RegExp 等类型数据;可通过 persist 配置 serialize/deserialize 函数处理,或改用时间戳、普通对象等轻量方案,敏感数据还可集成加密逻辑。

Pinia 本身不处理序列化,持久化插件(如 pinia-plugin-persistedstate)默认用 JSON.stringify 和 JSON.parse 存取数据。但 Date、Map、Set、RegExp、函数、undefined 等类型无法被 JSON 安全转换——它们会被丢弃、转为空对象或报错。要保留这类值,必须自定义序列化器。
为什么需要自定义序列化器
默认序列化会静默丢失以下内容:
- Date 实例 → 变成字符串(如
"2026-10-14T06:26:00.000Z"),还原后是普通字符串,不是 Date 对象 - Map / Set → 被转成空对象
{} - 正则表达式
/abc/g→ 变成空对象 - 带有方法或 Symbol 的对象 → 方法消失,Symbol 键被忽略
配置 serializer 的标准写法
在 store 的 persist 配置中传入 serializer 对象,包含 serialize 和 deserialize 两个函数:
export const useUserStore = defineStore('user', {
state: () => ({
lastLogin: new Date(),
preferences: new Map([['theme', 'dark']]),
filters: /active/i
}),
persist: {
serializer: {
serialize: (state) => {
return JSON.stringify({
...state,
lastLogin: state.lastLogin?.toISOString?.(),
preferences: Array.from(state.preferences.entries()),
filters: state.filters?.toString?.()
})
},
deserialize: (raw) => {
const obj = JSON.parse(raw)
return {
...obj,
lastLogin: obj.lastLogin ? new Date(obj.lastLogin) : null,
preferences: obj.preferences ? new Map(obj.preferences) : new Map(),
filters: obj.filters ? RegExp(obj.filters.split('/')[1], obj.filters.split('/')[2]) : null
}
}
}
}
})
更轻量的替代方案:只序列化关键字段
如果只是想保留 Date 或简单结构,不必重写整套逻辑。可先在 state 中做预处理:
- 把
lastLogin: new Date()改为lastLoginAt: Date.now()(存数字时间戳) - 把
preferences: new Map()改为普通对象preferences: { theme: 'dark' } - 把正则存为字符串
filterPattern: 'active',使用时再new RegExp(pattern)
这样就不需要自定义 serializer,也能避开 JSON 限制。
敏感数据加密场景下的序列化器
若需加密 token 或用户 ID,可在 serialize 中调用加密函数(如 AES 加密库),deserialize 中解密:
- 确保加密密钥不硬编码,建议从环境变量或安全上下文获取
- 解密失败时应有兜底逻辑(如返回初始 state,避免页面崩溃)
- 注意加密后数据体积增大,避免超出 localStorage 限制(通常 5–10MB)










