[已实现] iview-admin动态加载路由修改方法 · Issue #1158 · iview/iview-admin · GitHub
- -本示例基于iview-admin的template分支修改,其他分支应该也是支持的,通过mock方式模拟后台数据,将mock数据更改为自己的后端数据格式,转换方法稍加修改即可. @/mock/login.js中增加数据. 直接将@router/routers.js中,home节点到404节点之间的数据 __剪切 __过去即可.
本示例基于iview-admin的template分支修改,其他分支应该也是支持的,通过mock方式模拟后台数据,将mock数据更改为自己的后端数据格式,转换方法稍加修改即可
直接将@router/routers.js中,home节点到404节点之间的数据 __剪切 __过去即可
export const getUserMenus = req => {
return [
// 粘贴到这里就可以了
// 需要把所有的component: () => import('@/view/**/*.vue')
// 修改为component: 'view/**/*.vue'
// 注意main和parent-view
{
path: '',
name: 'doc',
meta: {
title: '文档',
href: 'https://lison16.github.io/iview-admin-doc/#/',
icon: 'ios-book'
}
},
{
path: '/multilevel',
name: 'multilevel',
meta: {
icon: 'md-menu',
title: '多级菜单'
},
component: 'components/main',
children: [
{
path: 'level_2_1',
name: 'level_2_1',
meta: {
icon: 'md-funnel',
title: '二级-1'
},
component: 'view/multilevel/level-2-1.vue'
},
{
path: 'level_2_2',
name: 'level_2_2',
meta: {
access: ['super_admin'],
icon: 'md-funnel',
showAlways: true,
title: '二级-2'
},
component: 'components/parent-view',
children: [
{
path: 'level_2_2_1',
name: 'level_2_2_1',
meta: {
icon: 'md-funnel',
title: '三级'
},
component: 'view/multilevel/level-2-2/level-3-1.vue'
}
]
},
{
path: 'level_2_3',
name: 'level_2_3',
meta: {
icon: 'md-funnel',
title: '二级-3'
},
component: 'view/multilevel/level-2-3.vue'
}
]
}
]
}Mock.mock(/\/get_user_menus/, getUserMenus)
export const listUserMenus = () => {
return axios.request({
url: 'get_user_menus',
method: 'get'
})
}/**
* @description 将后端菜单树转换为路由树
* @param {Array} menus
* @returns {Array}
*/
export const backendMenusToRouters = (menus) => {
let routers = []
forEach(menus, (menu) => {
// 将后端数据转换成路由数据
let route = backendMenuToRoute(menu)
// 如果后端数据有下级,则递归处理下级
if (menu.children && menu.children.length !== 0) {
route.children = backendMenusToRouters(menu.children)
}
routers.push(route)
})
return routers
}
/**
* @description 将后端菜单转换为路由
* @param {Object} menu
* @returns {Object}
*/
const backendMenuToRoute = (menu) => {
// 具体内容根据自己的数据结构来定,这里需要注意的一点是
// 原先routers写法是component: () => import('@/view/error-page/404.vue')
// 经过json数据转换,这里会丢失,所以需要按照上面提过的做转换,下面只写了核心点,其他自行处理
let route = Object.assign({}, menu)
route.component = () => import(`@/${menu.component}`)
return route
}export default {
state: {
routers: [],
hasGetRouter: false
},
getters: {
menuList: (state) => (state, getters, rootState) => getMenuByRouter(state.routers, rootState.user.access),
},
mutations: {
setRouters (state, routers) {
state.routers = routers
},
setHasGetRouter (state, status) {
state.hasGetRouter = status
}
},
actions: {
getRouters ({ commit }) {
return new Promise((resolve, reject) => {
try {
listUserMenus().then(res => {
let routers = backendMenusToRouters(res.data)
commit('setRouters', routers)
commit('setHasGetRouter', true)
resolve(routers)
}).catch(err => {
reject(err)
})
} catch (error) {
reject(error)
}
})
}
}
}const turnTo = (to, access, next) => {
if (canTurnTo(to.name, access, store.state.app.routers.concat(routes))) next() // 有权限,可访问
else next({ replace: true, name: 'error_401' }) // 无权限,重定向到401页面
}
// 修改这部分代码
if (store.state.user.hasGetInfo && store.state.app.hasGetRouter) {
turnTo(to, store.state.user.access, next)
} else {
// 加载用户信息
store.dispatch('getUserInfo').then(user => {
// 加载用户菜单
store.dispatch('getRouters').then(routers => {
// commonRoutes需要追加到路由解析最后的404,把原先的routers.js中的404删掉即可
router.addRoutes(routers.concat([
{
path: '*',
name: 'error_404',
meta: {
hideInMenu: true
},
component: () => import('@/view/error-page/404.vue')
}
]))
next({ ...to })
})
}).catch(() => {
setToken('')
next({ name: 'login' })
})
}需要修改注销的代码,注销成功后跳转到登录页面,这样可以起到强制刷新的作用,清空缓存的routers
logout () {
this.handleLogOut().then(() => {
window.location = '/login'
})