2.3 KiB
2.3 KiB
Context
多页签由 stores/modules/tabs.ts 按 path 追踪(持久化),layouts/default.vue 的 activePath watch 调 addTab,<router-view /> 直接渲染。菜单页面均为 index.vue(<script setup> 无显式 name),故 keep-alive 无法按组件名区分。动机见 proposal.md - Why。
Goals / Non-Goals
Goals:
- 布局内菜单页面切换页签保留状态,关闭页签销毁状态。
- keep-alive 按页面可配置:默认开启,页面可经路由 meta 关闭。
Non-Goals:
- 不缓存空白布局页(login/register/forgot-password/force-change-password/403,均不在本布局)。
Decisions
D1 — 缓存标识 = 组件 name(路径末段 kebab)
给 11 个菜单页面补 defineOptions({ name }),name 取路径末段 kebab-case(/→dashboard、/system/user→user、/monitor/login-log→login-log…),天然唯一无冲突。
- 备选:用 SFC 文件名派生(全是
index)——冲突,否决。
D2 — 默认缓存,路由 meta 可关闭(用户已拍板 opt-out)
页面默认缓存;在 <route> 里声明 meta.keepAlive: false 即关闭缓存。TabItem 新增 keepAlive 字段(addTab 时取 route.meta.keepAlive !== false)。
D3 — 布局 keep-alive + include 由「打开且未关闭缓存」的页签推导
layouts/default.vue 将 <router-view /> 改为:
<router-view v-slot="{ Component, route }">
<keep-alive :include="cachedNames">
<component :is="Component" :key="route.path" />
</keep-alive>
</router-view>
cachedNames = tabsStore.tabs.filter(t => t.keepAlive).map(t => pathToName(t.path)),pathToName 从 tabs store 导出。
D4 — 关闭页签 = 移出 include = 销毁
关闭页签即从 tabs 移除,cachedNames 不再含该 name,keep-alive 自动销毁缓存实例;重新打开时重建(重建后重新加载数据)。
Risks / Trade-offs
- [页面 name 与 pathToName 不一致 → 缓存静默失效] → 11 个 name 与 pathToName 采用同一约定,并在 type-check 外靠冒烟验证。
- [缓存页面数据陈旧] → 既有 useRequest 已在进入页面时按需拉取;重建/重新打开时重新请求,不影响正确性。
Migration Plan
无数据迁移;纯前端,回滚即撤销。
Open Questions
无。