// 我是直接把筛选封装成一个方法
// 筛选请求结果(父路由)
const menuList = (arr) => {
return arr.filter(item => {
return item.type === 0 // 这里type 0 是一级菜单标识
})
}
// 筛选请求结果(子路由)
const childrenMenuList = (arr) => {
return arr.filter(item => { // 这里type 1 是二级菜单标识
return item.type === 1
})
}
// 我是父路由和子路由分开匹配的,也就是两个方法,父路由一个匹配方法,子路由一个匹配方法
const RoutesFilter = (resRoutes, asyncRoutes) => { // 使用筛选出来的动态父路由权限匹配出父路由数组
const newRoutes = []
for (let i = 0; i < asyncRoutes.length; i++) {
const asyncRoute = asyncRoutes[i]
for (let j = 0; j < resRoutes.length; j++) {
const resRoute = resRoutes[j]
if (asyncRoute.name === resRoute.name) {
newRoutes.push(asyncRoute)
}
}
}
return newRoutes
}
const childrenRouteFilter = (resChildrenRoutes, asyncChildrenRoutes) => { // 使用筛选出来的动态子路由权限匹配出子路由数组
const newChildrenRoutes = []
for (let i = 0; i < asyncChildrenRoutes.length; i++) {
const asyncChildrenRoute = asyncChildrenRoutes[i]
for (let j = 0; j < resChildrenRoutes.length; j++) {
const resChildrenRoute = resChildrenRoutes[j]
if (asyncChildrenRoute.name === resChildrenRoute.name) {
newChildrenRoutes.push(asyncChildrenRoute)
}
}
}
return newChildrenRoutes
}
const actions = {
async generateRoutes({ commit }) {
try {
const res = await store.dispatch('user/userInfoAction') // 请求用户信息权限
const menuArr = menuList(res.data.menu) // 筛选父路由的动态权限
const childrenMenuArr = childrenMenuList(res.data.menu) // 筛选子路由的动态权限
const newRoutes = RoutesFilter(menuArr, asyncRoutes) // 父路由权限匹配方法
const newChildrenRoutes = childrenRouteFilter(childrenMenuArr, asyncChildrenRoutes) // 子路由权限匹配方法
const notChildrenRoutes = constantRoutes.concat(newRoutes) // 匹配出来的父路由于静态路由合并
// 目前只有系统管理模块有子路由所以,只需要找系统管理就可以了。如果之后有更多的模块拥有子路由那么需要在拥有子路由的父路由中增加一个识别状态,用来判断。
notChildrenRoutes.forEach(item => {
if (item.name === '系统管理') {
// 把上方匹配出来的子路由与静态子路由合并,再排序
item.children = bubbleSort(item.children.concat(newChildrenRoutes))
}
})
// 由于动态路由在刷新页面时会找不到路由而跳转到404页面。所有需要把404通配符* 从静态路由组中拿出来,使用动态加载到路由最后面
const routes = notChildrenRoutes.concat(route404)
// 对整个拼接出来的路由重新排序
const routesSortArr = bubbleSort(routes)
// 把排序好的路由数组赋值给router的原路由参数,把原路由参数替换成新的
router.options.routes = routesSortArr
// 由于使用router.addRoutes()方法注册新的router.options.routes会报路由名重复的警告
// 是因为路由信息还没初始化,信息里还存在原路由信息导致的路由名重复的警告
// 这里需要重新实例化一个Router,然后使用实例中的matcher把原router中的matcher初始化一下,就解决了报路由名重复的警告
router.matcher = new Router().matcher
// 在初始化之后, 再使用router.addRoutes()方法注册一下替换的路由。就成功激活路由了
router.addRoutes(router.options.routes)
// filterRoutes(menuArr, constantRoutes) // 根据权限设置父路由状态
// filterChildrenRoutes(childrenMenuArr, constantRoutes) // 根据权限设置子路由状态
commit('SET_ROUTES', { routes, menu: res.data.menu })
return Promise.resolve(constantRoutes)
} catch (err) {
throw new Error(err)
}
}
}
function bubbleSort(arr) { // 路由从小到大排序
const len = arr.length
for (let i = 0; i < len; i++) {
for (let j = 1; j < len - i; j++) {
if (arr[j - 1].meta.sort > arr[j].meta.sort) {
[arr[j - 1], arr[j]] = [arr[j], arr[j - 1]]
}
}
}
return arr
}
router.beforeEach(async (to, from, next) => {
NProgress.start()
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next()
NProgress.done()
} else {
// 这里利用vuex中的数据来处理重复请求的操作
const hasRoute = store.state.permission.newRoutes && store.state.permission.newRoutes.length > 0
if (hasRoute) {
next()
NProgress.done()
} else {
try {
await store.dispatch('permission/generateRoutes') // 权限菜单
next({ ...to, replace: true }) // 这里一定要加,replace,不然跳转会出问题。
NProgress.done()
} catch (error) {
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
vue2的动态路由
最新推荐文章于 2024-05-10 18:28:14 发布