Vue 3 用 Pinia 持久化存储(persist)之后,存储的组件无法渲染。
Vue 3 用 Pinia 持久化存储(persist)之后,存的组件(比如
component: markRaw(SomeComponent)
)无法渲染。
这其实是一个常见的坑,大概总结一下原因:
为什么持久化后组件无法渲染?#
因为:
Pinia persist 插件是通过
localStorage
/sessionStorage
持久化数据的。存进去的时候,会把你的对象转成
JSON
字符串。但是 Vue 组件(比如
Connections.vue
、LocalFolder.vue
这些)是函数对象,不能被 JSON 化!所以,你 markRaw () 后的组件,在持久化存进去的时候,其实丢失了!
变成了undefined
、空对象{}
或者直接没了。
→ 然后你在页面重新刷新、读取持久化数据后,就发现 component 是空的,自然报 missing template or render function 的错误。
直接总结:#
原因 | 解释 |
---|---|
JSON.stringify 不能序列化 Vue 组件 | 组件是函数 / 对象,不能持久化 |
Pinia persist 插件默认是 JSON 存储 | 持久化后 component 消失了 |
结果 | 页面重新渲染时找不到组件,直接爆炸 |
解决方案(正式版)#
最标准的处理是:
✅ 不要把组件本身持久化到 Storage。
而是只持久化 id
、title
、icon
这些轻量信息,component
应该在内存里动态注入!
怎么做?
比如改你的 MenuItem
类型:
interface MenuItem {
id: string;
icon: string;
title: string;
active: boolean;
component?: any; // 不持久化
}
但是存到 localStorage 时,只存:
{
id: 'files',
icon: 'mdi:folder',
title: '文件',
active: false
}
然后在 store
初始化的时候,根据 id
再补充上对应的 component。
实战例子:修改你的 useLeftMenuStore
#
import { defineStore } from 'pinia';
import { markRaw, ref } from 'vue';
import LocalFolder from '@/components/LocalFolder.vue';
import Connections from '@/components/terminal/Connections.vue';
import ScriptList from '@/components/scripts/ScriptList.vue';
const componentMap = {
terminal: markRaw(Connections),
files: markRaw(LocalFolder),
scripts: markRaw(ScriptList)
};
export const useLeftMenuStore = defineStore(
'leftMenu',
() => {
const menus = ref([
{ id: 'terminal', icon: 'mdi:console', title: '终端', active: true },
{ id: 'files', icon: 'mdi:folder', title: '文件', active: false },
{ id: 'scripts', icon: 'mdi:script-text', title: '脚本', active: false }
]);
const activeMenu = ref(menus.value[0]);
// 在应用启动时,给每个菜单动态加上 component
menus.value.forEach(menu => {
(menu as any).component = componentMap[menu.id];
});
const setActiveComponent = (item) => {
if (!item.active) {
menus.value.forEach((menu) => {
menu.active = menu.id === item.id;
});
activeMenu.value = item;
}
};
return {
menus,
activeMenu,
setActiveComponent
};
},
{ persist: true }
);
🔵 重点就是:
持久化只存
id
、title
、icon
。刷新后,根据
id
自动重新补充component
!
小结一句话#
Pinia Persist 不适合直接存 Vue 组件,要通过 ID 或 Key 去恢复。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: