侧边栏折叠状态持久化需用 pinia-plugin-persistedstate 插件,注册后在 layout store 中配置 paths: ['isCollapsed'] 实现 localStorage 自动存取,组件中通过 storeToRefs 响应式使用。

侧边栏折叠状态持久化,核心是把 isCollapsed 这类布尔值存进本地存储,并在应用启动时自动读取还原。Pinia 本身不保存数据,必须搭配插件实现,推荐用 pinia-plugin-persistedstate —— 它轻量、稳定、官方文档明确推荐,且对 H5 场景开箱即用。
安装并全局注册插件
先安装插件:
npm install pinia-plugin-persistedstate
然后在创建 Pinia 实例的地方(通常是 main.ts 或 src/stores/index.ts)注册它:
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
export default pinia
这一步完成后,所有后续 store 都具备了持久化能力基础,但具体是否启用、存哪些字段,由每个 store 自己决定。
在侧边栏 Store 中声明持久化配置
新建或复用一个管理布局状态的 store(比如叫 useLayoutStore),只暴露和持久化真正需要的字段:
- 用
paths: ['isCollapsed']精确控制——只存折叠状态,不存临时 UI 变量(如 hover 状态、动画开关) - 默认使用
localStorage,关掉浏览器再打开依然有效 - 避免直接写
persist: true,防止意外序列化不可存的值(如函数、undefined)
示例代码:
export const useLayoutStore = defineStore('layout', {
state: () => ({
isCollapsed: false,
// 其他不需持久化的字段,如 menuHoverKey、activeTab,不列入 paths
}),
persist: {
enabled: true,
paths: ['isCollapsed']
}
})
在组件中响应式使用和更新
在侧边栏组件(如 Sidebar.vue)里调用 store:
- 读取:直接访问
layoutStore.isCollapsed,它会自动从 localStorage 加载初始值 - 更新:修改后插件自动触发
localStorage.setItem,无需手动调用 - 注意不要在
state中放无法 JSON 序列化的值(如 DOM 节点、Date 对象),否则恢复时该字段会丢失
常见写法:
<template><el-aside :class="{ 'is-collapsed': isCollapsed }"><button>{{ isCollapsed ? '展开' : '折叠' }}</button>
</el-aside></template><script setup>
import { useLayoutStore } from '@/stores/layout'
const layoutStore = useLayoutStore()
const { isCollapsed } = storeToRefs(layoutStore)
const toggleCollapse = () => {
layoutStore.isCollapsed = !layoutStore.isCollapsed
}
</script>
补充建议与避坑点
实际项目中容易忽略但影响体验的细节:
- 如果侧边栏状态要和用户身份绑定(比如不同账号有不同默认折叠状态),可把 key 改为带用户 ID 的形式:
key: `layout-${userId}` - 首次加载时若 localStorage 没有值,
isCollapsed会按state中定义的默认值(false)初始化,行为可预期 - 不要在
persist中存大对象(如整个菜单树),只存控制状态的开关字段,减少序列化开销 - 调试时可加
debug: true查看插件是否成功读写,例如:persist: { enabled: true, paths: ['isCollapsed'], debug: true }










