解决使用router.addRoutes()设置动态路由,页面刷新后无效

最近在搞一个vue后台管理平台的项目,记录一下最近项目中遇到的一个坑,就是使用router.addRoutes()设置动态路由,页面刷新后重定向到了404,后来经过几天的研究才找到的真正的原因。

原来是我在登陆之后把路由列表转换成了字符串类型数据存在了本地,当取出来的时候在转换成JSON时候

发现发生这种问题的根本原因在于路由component参数在被json转换成字符串之后,然后转回对象的时候无法解析

找到根本原因后问题后问题就迎刃而解了

 

 

参考文献 https://segmentfault.com/q/1010000009524078

               https://forum.vuejs.org/t/vue-router-3-0-1-router-addroutes/33181/6

              

<think>我们正在讨论前端路由系统中使用`addRoutes`方法添加子路由的实现方式。根据引用内容,我们可以总结出以下几点关键信息: 1.Vue页面应用中,动态添加路由(`addRoutes`)需要在正确的时机执行。引用[1]指出,如果在具体页面中执行`addRoutes`,由于路由表的处理逻辑早已在侧边栏等渲染时完成,所以添加会无效。 2. 引用[2]展示了在登录后获取路由信息,存储在Vuex中,然后调用一个初始化路由的方法(`initRoutes`)来动态添加路由。 3. 引用[3]提到有两种方式加载权限侧边栏,并建议采用后台主导的方式,即后台返回的路由信息能够直接用于前端路由配置,避免前后端耦合。 因此,实现动态添加子路由的正确方式应该是: - 在应用初始化时(如登录后,或应用启动时)获取路由配置信息(通常从后台API获取)。 - 将获取的路由配置信息存储到Vuex中,以便全局访问。 - 在路由守卫(如全局前置守卫`router.beforeEach`)或应用初始化逻辑中,使用`router.addRoutes`方法将存储的路由配置动态添加到路由实例中。 下面是一个具体的实现步骤: ### 步骤1:定义路由实例 首先,在创建Vue路由实例时,只初始化一些公共路由(如登录页、404页等),而将需要权限控制的路由留空,等待动态添加。 ```javascript // router/index.js import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const router = new Router({ mode: 'history', routes: [ // 公共路由 { path: '/login', component: () => import('@/views/Login.vue') }, { path: '/404', component: () => import('@/views/404.vue') }, // ...其他公共路由 ] }) ``` ### 步骤2:获取路由配置并存储 在用户登录后,从后台获取该用户有权访问的路由配置(通常是一个树形结构,包含父路由和子路由)。然后将这个路由配置存储到Vuex中。 ```javascript // 在登录成功后,或者在应用初始化时(如通过token自动登录) async function getRoutes() { try { // 假设调用API获取路由配置 const navList = await api.getUserRoutes() // 将路由配置存储到Vuex store.commit('setRoutes', navList) } catch (error) { console.error(error) } } ``` ### 步骤3:动态添加路由 定义一个方法,用于将存储在Vuex中的路由配置转换成Vue Router可识别的路由格式,并使用`router.addRoutes`添加到路由实例中。 ```javascript // router/index.js export function initRoutes() { // 从Vuex中获取路由配置 const routes = store.getters.routes // 将路由配置转换为路由记录 const routeConfigs = formatRoutes(routes) // 需要编写一个转换函数,将后台返回的配置转换成路由对象 // 动态添加路由 router.addRoutes(routeConfigs) // 同时,添加一个404路由捕获未匹配的路由(注意:要在最后添加) router.addRoutes([ { path: '*', redirect: '/404' } ]) } // 转换函数示例:将后台返回的配置转换为路由对象 function formatRoutes(routes) { return routes.map(route => { const { path, component, children, ...rest } = route // 注意:组件需要动态导入,例如:component: () => import(`@/views${component}`) // 但要注意,如果后台返回的是组件路径字符串,需要确保路径正确且webpack能处理 return { path, component: () => import(`@/views${component}.vue`), // 假设后台返回的component是字符串,如'/system/marketTopics' ...rest, children: children ? formatRoutes(children) : [] } }) } ``` ### 步骤4:在适当的时候调用初始化路由 在登录成功后,或者在应用初始化时(比如通过token检查用户已登录),调用`initRoutes`方法。 ```javascript // 在登录成功的回调中,或者在全局前置守卫中 router.beforeEach((to, from, next) => { if (to.path === '/login') { next() } else { // 检查用户是否已登录 if (store.getters.token) { // 检查是否已经添加过动态路由 if (!store.getters.routesAdded) { // 获取路由配置并添加 getRoutes().then(() => { initRoutes() store.commit('setRoutesAdded', true) // 注意:添加路由后,需要重定向到目标路由,因为添加的路由可能包含当前要访问的路由 next({ ...to, replace: true }) // 确保路由添加后,重新进入当前路由 }) } else { next() } } else { next('/login') } } }) ``` ### 注意事项 1. **路由重复添加**:避免重复调用`addRoutes`,否则会导致控制台警告。可以通过Vuex状态来记录是否已经添加过路由。 2. **404路由**:动态添加路由后,需要确保404路由在最后添加,否则它会匹配所有未定义的路由。 3. **组件路径**:后台返回的路由配置中,组件路径需要与前端项目中的实际路径匹配,并且使用动态导入(`import()`)来按需加载。 4. **路由顺序**:动态添加的路由应该在公共路由之后,因此404路由应该在最后添加。 ### 相关问题 1. 如何避免动态添加路由时出现重复路由? 2. 动态添加路由后,如何更新侧边栏菜单? 3. 如果后台返回的路由配置包含嵌套路由(子路由),如何正确转换并添加到路由实例中? 4.Vue3中使用Vue Router 4,动态添加路由的方法有什么变化? 以上实现方式能够满足在Vue页面应用中动态添加子路由的需求,并且符合前后端分离的设计思想,由后台主导路由配置。</think>### 前端路由 addRoutes 添加子路由的实现方式 在 Vue.js 的路由系统中,使用 `addRoutes` 动态添加子路由的实现需要遵循以下关键步骤: #### 1. **初始化路由实例** ```javascript // router/index.js import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) // 初始路由(公共路由) const baseRoutes = [ { path: '/login', component: () => import('@/views/Login.vue') }, { path: '/404', component: () => import('@/views/404.vue') } ] const router = new Router({ mode: 'history', routes: baseRoutes }) export default router ``` #### 2. **定义动态添加路由的方法** ```javascript // 动态路由注入函数 export function initRoutes() { const dynamicRoutes = [ { path: '/dashboard', component: () => import('@/layouts/MainLayout.vue'), children: [ // 子路由示例 { path: 'users', component: () => import('@/views/UserList.vue'), // 嵌套子路由 children: [ { path: ':id', component: () => import('@/views/UserDetail.vue') } ] }, { path: 'settings', component: () => import('@/views/Settings.vue') } ] } ] // 核心:添加子路由 router.addRoutes(dynamicRoutes) } ``` #### 3. **在正确时机调用添加方法** ```javascript // 登录成功后调用 async login() { const res = await api.login() if (res.success) { // 1. 获取动态路由配置 (通常从API获取) const navList = await api.getUserRoutes() // 2. 存储到Vuex this.$store.commit('setPermissionRoutes', navList) // 3. 动态注入路由 initRoutes() // 4. 跳转到主页 this.$router.push('/dashboard') } } ``` #### 4. **解决侧边栏渲染问题** ```javascript // 在布局组件中监听路由变化 // layouts/MainLayout.vue export default { computed: { permissionRoutes() { return this.$store.state.permissionRoutes } }, watch: { // 路由更新时刷新菜单 '$route'() { this.$refs.sidebar.refreshMenu() } } } ``` ### 关键注意事项 1. **添加时机** 必须在路由初始化**之后**调用 `addRoutes`,通常在登录成功或应用初始化时执行。在具体页面组件中添加会失效,因为父级布局组件已渲染完成[^1]。 2. **路由格式** 子路由需嵌套在 `children` 属性中: ```javascript { path: '/parent', component: ParentComponent, children: [ // 子路由数组 { path: 'child', component: ChildComponent } ] } ``` 3. **Vuex 状态管理** 存储路由配置用于侧边栏渲染: ```javascript // store/modules/permission.js state: { routes: [] }, mutations: { setRoutes(state, routes) { state.routes = baseRoutes.concat(routes) // 合并基础路由 } } ``` 4. **404 路由处理** 动态路由需在最后添加通配路由: ```javascript router.addRoutes([ ...dynamicRoutes, { path: '*', redirect: '/404' } // 必须放在最后 ]) ``` ### 工作流程示意图 ```mermaid graph TD A[用户登录] --> B[获取权限路由配置] B --> C[存储到Vuex] C --> D[调用 addRoutes] D --> E[路由系统更新] E --> F[侧边栏读取Vuex渲染] ``` > **重要提示**:在 Vue Router 4.x 中,`addRoutes` 已被 `addRoute` 替代,支持单独添加路由记录: > ```javascript > router.addRoute({ > path: '/new', > component: NewComponent, > children: [...] // 添加嵌套子路由 > }) > ``` ### 相关问题 1. 如何解决动态添加路由页面刷新的白屏问题? 2. Vue Router 4.x 与 3.x 在动态路由处理上有哪些差异? 3. 如何实现动态路由的权限验证和路由守卫? 4. 动态添加的路由在热重载(HMR)时会出现什么问题?如何解决? [^1]: 动态路由添加时机不当会导致失效 [^2]: 登录时获取路由配置并存储到 Vuex [^3]: 后台主导的路由配置方案更符合前后端分离
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值