关于Vue3动态添加路由后,刷新页面路由丢失的解决

问题描述:在实现根据角色权限动态添加路由的功能时,遇到了麻烦。本人动态添加路由的思路如下:在登录时去后端获取路由信息,然后动态添加,再跳转主页。这个实现思路让我成功跳转主页后能够使用添加的动态路由,然而,一旦刷新页面,添加的动态路由就会丢失

解决过程

1. 在index.ts中(本人的路由文件,router/index.ts,配置静态路由和路由守卫所在的文件),发现每次刷新页面整个index.ts文件会整个重新执行,而其他操作(页面的前进、后退等)则只会由于执行路由守卫。那么重点就是,利用整个页面刷新的这种特性,在index.ts中,路由守卫外,设置一个标志,来判断页面是否被刷新。一旦页面被刷新,说明动态路由丢失,需要重新添加

2. 再判断完页面刷新后,还有一个问题,由于router.addRoute()是异步操作,在它没添加完成时,可能就执行了next()去跳转页面,此时就不能找到路由信息,还是会白屏。如下图

解决方法如下

当页面被刷新时,会触发路由守卫,此时count==1执行了添加动态路由的方法,由于是异步操作,它没执行完就执行了next(to.fullPath)再次触发路由守卫,count++,等到重新回到这一个地方,异步操作已经完成了,路由添加完毕,此时count==2,不会执行if里面的动态路由添加方法,而是执行else里面的next直接跳转目标页面。问题彻底解决。

吐槽一句,网上找的解决方法大多无法解决,最后是在B站一个视频里找到的灵感,如果看不懂我的方法,可以去看看这个视频。贴一下视频链接:【vue3实战5.13-处理动态添加的路由刷新白屏】 https://www.bilibili.com/video/BV1QC4y1n7wK/?share_source=copy_web&vd_source=5c5e132774852e5a176f1d8cbb4c4134

### Vue 动态添加路由刷新路由图标字段丢失解决方案 在 Vue 中实现动态路由时,如果遇到刷新页面路由配置中的自定义字段(如 `meta.icon` 或其他扩展属性)丢失的情况,通常是因为这些字段并未持久化到服务端或未通过某种机制重新加载。以下是针对此问题的具体分析与解决方法: #### 1. **原因分析** 当浏览器刷新时,Vue 应用会重新启动,此时仅保留静态路由配置,而动态路由则需要再次从服务端拉取并注册。如果没有正确处理动态路由的元信息(如 `icon`),就会导致这些字段丢失。 根据已有描述[^2]和实际开发经验可知,动态路由的核心在于如何将后端返回的数据转换为合法的路由对象,并将其注入到 Vue Router 的实例中。 --- #### 2. **解决思路** ##### 方法一:确保动态路由数据结构完整 在请求后端接口获取路由列表时,应保证返回的数据包含完整的路由配置信息,包括但不限于路径 (`path`)、名称 (`name`) 和元信息 (`meta`)。例如: ```javascript const menuDataFromServer = [ { path: '/dashboard', name: 'Dashboard', meta: { icon: 'home', title: '首页' }, children: [] } ]; ``` 随后可以通过工具函数将上述数据转化为标准的 Vue Router 配置项。具体逻辑如下所示[^3]: ```javascript function generateRouters(menuList) { const result = []; menuList.forEach(item => { const route = { path: item.path, component: () => import(`@/views${item.component}`), // 假设组件路径已知 name: item.name, meta: item.meta || {} }; if (item.children && item.children.length > 0) { route.children = generateRouters(item.children); } result.push(route); }); return result; } ``` 最后,在应用初始化阶段完成动态路由的挂载操作: ```javascript import Vue from 'vue'; import Router from 'vue-router'; // 初始化基础路由 const constantRouterMap = [{ path: '/', redirect: '/login' }]; let dynamicRouterMap = []; Vue.use(Router); export function createRouter() { const router = new Router({ mode: 'history', routes: [...constantRouterMap] }); // 添加全局前置守卫 router.beforeEach(async (to, from, next) => { if (!dynamicRouterMap.length) { try { const res = await fetch('/api/getMenu'); // 请求后端菜单数据 const menuData = await res.json(); dynamicRouterMap = generateRouters(menuData); // 转换为路由配置 router.addRoutes(dynamicRouterMap); // 注册动态路由 } catch (error) { console.error('Failed to load dynamic routers:', error); } } next(); }); return router; } ``` 此处的关键点在于利用 `router.addRoutes()` 将生成后的动态路由追加至当前路由器实例上[^4]。 --- ##### 方法二:存储状态于本地缓存 为了进一步优化用户体验,可以考虑借助 LocalStorage 或 Vuex 来保存用户的权限范围及其对应的路由表。这样即便发生页面刷新,也可以快速恢复之前的路由配置而不必每次都向服务端发起请求。 示例代码片段展示如何结合 Vuex 实现这一功能: ```javascript // store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { routers: [], addRouters: [] }, mutations: { SET_ROUTERS(state, routers) { state.routers = routers; state.addRouters = routers.filter(router => !/^\/(login|register)/.test(router.path)); } }, actions: { GenerateRoutes({ commit }, roles) { return new Promise(resolve => { let accessedRouters; if (roles.includes('admin')) { accessedRouters = allRouters; // 所有可用路由 } else { accessedRouters = filterAsyncRoutes(allRouters, roles); // 过滤出对应角色可访问的部分 } commit('SET_ROUTERS', accessedRouters); resolve(accessedRouters); }); } } }); ``` 接着修改前面提到的 `beforeEach` 守护钩子部分,使其优先尝试读取 Store 数据而非直接依赖网络通信: ```javascript if (!store.getters.addRouters.length) { await store.dispatch('GenerateRoutes', userRoles); } dynamicRouterMap = store.getters.addRouters; if (dynamicRouterMap.length) { router.addRoutes(dynamicRouterMap); } next(to); ``` 这种方法不仅提升了性能还增强了系统的健壮性[^1]。 --- #### 总结 综上所述,要彻底解决 Vue 动态路由刷新丢失自定义字段的问题,需做到以下几点: - 后端提供全面且标准化的路由 JSON 结构; - 正确解析该结构并通过程序手段映射成适合 Vue Router 使用的形式; - 可选地引入客户端侧的状态管理技术来减少不必要的重复劳动。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值