路由守卫中通过Pinia Store统一管理弹窗状态,守卫仅调用open()触发状态变更,弹窗组件响应式渲染并接管导航流程,避免DOM操作与逻辑耦合。
在
路由
守卫中注入全局弹窗组件,核心不是“挂载 DOM”,而是让弹窗能力成为可被守卫逻辑直接调用的状态响应工具。关键在于解耦弹窗实例与路由逻辑,通过状态(如 pinia store 或 reactive 对象)驱动弹窗显隐和内容,再由守卫按需触发状态变更。
用 Pinia Store 统一管理弹窗状态
把弹窗的开关、类型、参数、回调都收归一个 store 管理,避免在守卫里 new 实例或操作 DOM:
定义
,含
、
、
、
等字段
在弹窗组件内部使用
响应式监听
和
,自动渲染对应内容
守卫中只需调用
,不接触 DOM 或 Vue 实例
在 beforeEach 中按需触发弹窗状态
守卫不再负责创建或挂载,只做决策:是否弹、弹什么、后续怎么走:
灵活路由的PHP库
灵活路由的PHP库
下载
检查
且用户未登录 → 调用
检查
且表单已修改 → 弹确认框,
回调里执行
,取消则
所有弹窗关闭后,统一在 store 的
方法里调用
或重定向,避免守卫内逻辑分散
弹窗组件自身响应状态并接管流程
组件不是被动展示,而是主动参与导航生命周期:
组件 mounted 后自动聚焦输入框,或播放提示音,增强反馈感
点击“确定”时,先执行传入的
(可能是登录请求),成功后再调用
支持 ESC 关闭、遮罩点击关闭,关闭时自动触发
或恢复上一导航状态
组件内不写
,只发事件或调 store 方法;守卫订阅 store 变化来推进导航
避免常见陷阱
状态驱动方案容易踩的坑:
不要在守卫里多次调用
导致弹窗叠加 —— store 应保证单例,
自动
前一个
不要把异步结果(如登录接口)硬塞进守卫的
回调 —— 应由弹窗组件内部 resolve promise,store 再通知守卫继续
服务端渲染(SSR)下,
不可用,此时弹窗 store 应兼容客户端懒初始化,组件用
安全渲染
useDialogStoreshow: booleantype: 'login' | 'confirm' | 'tip'payload: anyonConfirm: () => voidstoreToRefsshowtypedialogStore.open('login', { from: to.path }, () => next())to.meta.requiresAuth === truedialogStore.openLogin({ redirect: to.fullPath })to.meta.confirmLeave === trueonConfirmnext()next(false)closenext()onConfirmdialogStore.close()onCancelnextopen()open()close()next()document.bodyv-if="$route && dialogStore.show"