Vue + Vite 项目中动态路由刷新失效的解决方案

Vue + Vite 项目中动态路由刷新失效的解决方案

在基于 Vue3 + Vite 的中后台项目中,动态路由 + 登录鉴权 是常见的权限控制方案。然而,我们往往会遇到一个恼人的问题:刷新页面后,动态路由失效,页面跳转失败,控制台中 to.matched 为空,或者提示找不到对应路由。

一、问题描述

1.动态路由流程简述

我们的项目采用后端控制菜单 + 前端动态生成路由的方式。用户登录后:

  1. 发送登录请求,获取 token;

  2. 请求用户权限与菜单数据;

  3. 根据菜单生成动态路由,并通过 router.addRoute() 添加到路由表;

  4. 页面跳转至第一个可访问页面。

2.刷新场景下的问题

在开发环境(以 Vite 为例)中,刷新页面时会触发以下一系列重置流程:

  1. 所有运行状态被清空;

  2. 重新从 vite.config.ts 中的入口文件(通常是 main.ts)加载;

  3. 执行 Vue 应用初始化流程,包括挂载路由等。

此时路由表中仅有静态路由,原本通过登录后 addRoute() 添加的动态路由已经不存在。

此时若刷新的是一个动态页面路径,例如:https://example.com/layout/system/user,那么 Vue Router 会立即尝试匹配该路径,但此时你还没有注册这条路由,因此

  1. to.matched.length === 0
  2. 页面报错或白屏
  3. 控制台提示找不到组件等

二、解决方案

为了解决上述问题,我们从两个方面入手:

1. 路由数据持久化

创建 useMenuStore 来管理后端返回的菜单列表:

export const useMenuStore = defineStore('menu', {
  state: () => {
    return {
      menuList: [],
      firstMenu: '',
    }
  },
  persist: {
    enabled: true,
    storage: sessionStorage,
  }
})

当用户登录成功后,将后端返回的菜单原封不动存入 menuList,使用动态路由生成函数(例如 generateRoutes(menuList))遍历该列表生成前端路由对象,通过 router.addRoute(‘layout’, route) 将路由添加到主框架的子路由中。

使用 pinia-plugin-persistedstate 插件将 useUserStore 和 useMenuStore 持久化,确保刷新后可以从 localStorage 或 sessionStorage 中恢复数据。

2. 在合适的时机添加动态路由

在首次刷新时,重新注册动态路由。为了避免每次跳转都执行添加操作,引入 isRefresh 标志位,在 router/permission.ts 中添加:

let isRefresh = true
router.beforeEach((to, from, next) => {
  // 刷新且token有效才可以
  if(!refresh && useUserStore.token){
    refresh = true
    dynamicRoute(useMenuStore().menuList)
    // 关键点:重新跳转一次,确保路由匹配
    return next({...to,replace:true})
  }
}

问题大致解决思路就是这样,具体代码要根据项目不同做修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值