一.先设置生成路由的格式
- 假设业务路由放在
@/view/,路由文件结构模式如图(其中menuManage与userManage为业务路由):
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//1.基础路由
const basicRoutes=[
{
path: '/',
redirect: '/index',
},
{
path: '/index',
name: 'index',
meta: { isBanner: true },
component: () => import('@/views/home/index.vue'),
},
{
path: '/login',
name: 'login',
meta: { isBanner: true },
component: () => import('@/views/login/login.vue'),
},]
//2.创建路由
function createRouter() {
return new VueRouter({
mode: 'hash',
scrollBehavior: () => ({ y: 0 }),
routes: basicRoutes,
})
}
const router = createRouter()
//3.初始路由
export const resetRouter = () => {
router.matcher = createRouter().matcher
}
//4.路由导航
router.beforeEach((to, from, next) => {
const beforeLoginRoutes = ['index', 'login']
const loginRefuse = ['/login']
//这可以换成token
const isLogin = sessionStorage.getItem('isLogin')
if (isLogin) {
if (loginRefuse.indexOf(to.path) !== -1) {
console.log('登录后拒绝', to.path)
next(false)
} else {
console.log('登录后', to.name)
next()
}
} else {
if (beforeLoginRoutes.includes(to.name)) {
console.log('登录前正常', to.name)
next()
} else {
console.log('登录前拒绝', to.name)
next('/login')
}
}
})
export default router
// 额外路由(详情页编辑页等等)-----可另写js存放,这里为图方便
export const extraRoutes = {
manageCenter: [
{
path: `/manageCenter/menuManage/menuManageDetail`,
component: () => import(`@/views/manageCenter/menuManage/menuManageDetail.vue`),
name: 'menuManageDetail',
meta: {
// 在某个激活页面跳到属于该页面的详情页,保持激活状态不变(通过此值判断)
activeUrl: 'menuManage',
},
},
],
}
二. 在store的perims.js中获取后台数据并生成路由
//store/perims.js
import vueRouter from '../../router'
import { resetRouter } from '../../router'
import { extraRoutes } from '../../router'
function deep(list, keyName) => {
let newList = []
for (let i = 0, leng = list.length; i < leng; i++) {
if (list[i][keyName] && list[i][keyName].length > 0) {
const data = deep(list[i][keyName], keyName)
newList.push(...data)
} else {
newList.push(list[i])
}
}
return newList
}
const index={
state: {
// 处理过后的路由
menuData: {},
// 切换的展示菜单
showMenuData: [],
topMenuData: ['index'],
},
mutations: {
SET_MENU(state, data) {
state.menuData = data
},
SET_SHOWMENU(state, data) {
state.showMenuData = data
},
//2.1. 将路由动态生成,可根据后端数据自定义meta
SET_PERMISSION(state, router) {
//动态添加路由
if (router.route.length == 0) {
return
}
//生成子路由
const listRoutes = router.route.map((item) => {
return {
path: `/${router.routeType}/${item.permitUrl}`,
component: () => import(`@/views/${router.routeType}/${item.permitUrl}/index.vue`),
name: item.permitUrl,
meta: { activeUrl: item.permitUrl, routeType: router.routeType },
}
})
// 生成顶部路由,并将对应子路由嵌进去
const routes = [
{
path: `/${router.routeType}`,
component: () => import(`@/views/${router.routeType}/index.vue`),
redirect: `/${router.routeType}/${router.route[0].permitUrl}`,
children: listRoutes.concat(extraRoutes[router.routeType]),
},
]
vueRouter.addRoutes(routes)
},
},
actions: {
// 4. 可在顶部路由点击中调用此函数,切换菜单
setShowMenuData({ commit, state }, topType) {
// 存储菜单类别
sessionStorage.setItem('topType', topType)
commit('SET_SHOWMENU', state.menuData[topType])
},
// 1.在登录后调用该函数
getPermisson({ commit, state }) {
//重置路由到初始
//(若是通过接口频繁切换生成菜单可使用,防止生成重复路由,若是一次性生成路由没必要)
// resetRouter()
//后端传的数据格式如下(注意其中的一级数据为顶部路由,通过切换顶部路由,切换菜单)
let menuRoute = [
{
permitName: '管理中心',
permitUrl: 'manageCenter',
showName: '管理中心',
subList: [
{
permitName: '菜单管理',
permitUrl: 'menuManage',
showName: '菜单管理',
icon: 'menuIcon_moneyExcel'},
{
permitName: '用户管理',
permitUrl: 'userManage',
showName: '用户管理',
icon: 'userManage'}
]
let menuData = {}
menuRoute.forEach((item) => {
menuData[item.permitUrl] = item.subList
// 动态获取顶部路由
state.topMenuData.push(item.permitUrl)
//2.0 动态生成路由,其中的deep是将后台传过来的路由 递归过滤出来
commit('SET_PERMISSION', { routeType: item.permitUrl, route: deep(item.subList, 'subList') })
})
// 3.存储过滤后的菜单数据格式
commit('SET_MENU', menuData)
},
}
总结
若要在刷新页面保持菜单数据,可以将获取数据的接口放在App.vue的created函数里,并判断在用户已登录状态下获取菜单数据。这样可以不用将菜单数据存在本地,其用户信息类似。
注意:这里的方式适用于后台管理类的系统,若想扩展,思路类似,敬请探索。若有BUG,欢迎指正