Vue动态路由绑定页面刷新报错(Duplicate named routes definition)求助
问题描述
我是一名Java程序员,最近在学习Vue的动态路由绑定功能。一开始能正常导航到各个子路由,没有报错,但在子路由页面刷新时,出现了Duplicate named routes definition错误。
router/index.js
import Vue, { computed } from 'vue' import VueRouter from 'vue-router' import store from '../store/index' import axios from 'axios' Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: () => import('../views/Home.vue'), children: [ { path: '/index', name: 'Index', component: () => import('../views/Index.vue') }, ] }, { path: '/login', name: 'Login', component: () => import('../views/Login.vue') }, ] const router = new VueRouter({ routes }) router.beforeEach((to, from, next) => { let hasRouter = store.state.menus.hasRouter if (!hasRouter) { axios.get('/sys/menu/nav').then( res => { store.commit('setMenuList', res.data.data.menuList) store.commit('setPermList', res.data.data.permList) res.data.data.menuList.forEach( menu => { if (menu.children.length > 0) { menu.children.forEach(e => { // 转成路由 let route = menuToRoute(e) if (route) { router.addRoute('Home', route) } }) } } ) router.addRoute('Home', { path: '*', name: 'ERROR404', component: () => import('../views/error404.vue') }) store.commit('sethasRouter', true) } ) } next() }) const menuToRoute = (menu) => { if (!menu.component) { return null; } let route = { name: menu.name, path: menu.path, meta: { title: menu.title, icon: menu.icon } } route.component = () => import(`@/views/${menu.component}`) return route } export default router
mock data
Mock.mock('/sys/menu/nav', 'get', () => { // 菜单json let menuList = [ { id: 1, name: 'SysManga', title: '系统管理', icon: 'el-icon-s-operation', path: '/SysManga', component: '', children: [ { id :2, name: 'SysUser', title: '用户管理', icon: 'el-icon-s-custom', path: '/sys/users', component: 'sys/User', children: [] }, { id :3, name: 'SysRole', title: '角色管理', icon: 'el-icon-rank', path: '/sys/role', component: 'sys/Role', children: [] }, { id :4, name: 'SysMenu', title: '菜单管理', icon: 'el-icon-menu', path: '/sys/menu', component: 'sys/Menu', children: [] } ] }, { id :5, name: 'SysTools', title: '系统工具', icon: 'el-icon-s-tools', path: '/SysTools', children: [ { id :6, name: 'SysDict', title: '数字字典', icon: 'el-icon-s-order', path: '/sys/dicts', component: 'sys/Dicts', children: [] }, ] }] // 权限数据 let permList =['SysUser', "SysUser:save"] result.data = { menuList: [], permList: [] } result.data.menuList = menuList result.data.permList = permList return result })
问题原因与解决方法
问题原因
刷新页面时,beforeEach钩子会重新执行:
- axios请求是异步的,钩子末尾的
next()会先执行,此时动态路由还未添加完成就跳转页面; - 异步请求完成后,会再次添加相同的动态路由,导致路由命名重复;
- 页面刷新后Vuex状态重置,
hasRouter变回false,每次刷新都会重复执行路由添加逻辑。
解决方法
1. 修正路由导航逻辑
修改beforeEach钩子,确保动态路由添加完成后再执行导航,避免重复添加:
router.beforeEach((to, from, next) => { let hasRouter = store.state.menus.hasRouter if (!hasRouter) { axios.get('/sys/menu/nav').then( res => { store.commit('setMenuList', res.data.data.menuList) store.commit('setPermList', res.data.data.permList) res.data.data.menuList.forEach( menu => { if (menu.children.length > 0) { menu.children.forEach(e => { let route = menuToRoute(e) if (route) { router.addRoute('Home', route) } }) } } ) router.addRoute('Home', { path: '*', name: 'ERROR404', component: () => import('../views/error404.vue') }) store.commit('sethasRouter', true) // 添加完路由后重新导航,确保路由生效 next({ ...to, replace: true }) } ) } else { // 已存在路由,正常跳转 next() } })
2. 可选:持久化Vuex状态
页面刷新后Vuex状态会重置,若想避免每次刷新都重新请求接口,可将hasRouter和菜单数据持久化到localStorage:
- 在store的mutations中添加持久化逻辑:
mutations: { sethasRouter(state, value) { state.menus.hasRouter = value localStorage.setItem('hasRouter', JSON.stringify(value)) }, setMenuList(state, list) { state.menus.menuList = list localStorage.setItem('menuList', JSON.stringify(list)) } }
- 在store初始化时读取本地存储:
const state = { menus: { hasRouter: JSON.parse(localStorage.getItem('hasRouter')) || false, menuList: JSON.parse(localStorage.getItem('menuList')) || [] } }
内容的提问来源于stack exchange,提问作者evelynn9
相关产品推荐
相关产品推荐

