根据权限动态加载菜单

基础路由
const routes = [{
		path: '/login',
		hidden: true,
		meta: {
			layout: 'blank'
		},
		component: () => import( /* webpackChunkName: "user" */ '../views/user/login.vue')
	},
	{
		path: '/home',
		name: '首页',
		component: Home,
		meta: {
			// 固定在头部nav
			fixed: true
		},
		icon: 'home'
	},
	{
		path: '/404',
		hidden: true,
		component: () => import('../views/404.vue'),
		meta: {
			layout: 'blank'
		}
	}
]
路由初始化
// 对路由增加了缓存,刷新页面时无需二次动态获取
let _routes = !!sessionStorage.getItem("routes") ? getRenderRoutes(JSON.parse(sessionStorage.getItem("routes"))) : routes;
const router = new VueRouter({
	mode: 'history',
	base: process.env.BASE_URL,
	routes: _routes
})
动态获取路由并更新
router.beforeEach((to, from, next) => {
	// 如果跳转到登录页,就清楚所有缓存
	if (to.path === "/login") {
		clearAllData(store);
	}else {
		// userRole为空表示未登录
		if(!store.state.user.userInfo.userRole) {
			next('/login');
			return;
		}
	}
	if (!sessionStorage.getItem("routes") && !!store.state.user.userInfo.userRole) {
		let role = store.state.user.userInfo.userRole;
		// ***核心内容,其他可作为一个完善思路***
		getMenu(role).then(res => {
			if (res.data && res.data.length > 0) {
				// 下面的数据组装根据各自实际情况
				let par = res.data.filter(item => +item.menuType === 0);
				let child = res.data.filter(item => +item.menuType === 1);
				let menu = par.map(item => {
					let tmp = child.filter(i => i.parentId === item.id)
					item.childrens = tmp;
					return item;
				})
				// 将接口返回的数据存入sessionStorage
				sessionStorage.setItem("routes", JSON.stringify(menu));
				// 组装数据为路由标准格式
				let renderRoutes = getRenderRoutes(menu);
				// 此处更改router.matcher更优,如果用addRoutes()当角色转换时路由会出现问题
				router.matcher = new VueRouter({
					routes: renderRoutes
				}).matcher;
			}
			next()
			return;
		})
	}
	next()
})
function getRenderRoutes(data) {
	let menus = formatRoutes(data);
	// 404页面必须放在路由的最后
	let unfound = {
		path: '*',
		redirect: '/404',
		hidden: true
	};
	menus.push(unfound);
	let result = routes.concat(menus);
	return result;
}
function formatRoutes(aMenu) {
	// 除了route必须的属性之外,其他属性各自而定
	const aRouter = []
	aMenu.forEach(oMenu => {
		const {
			url,
			component,
			name,
			icon,
			childrens,
			alwaysShow,
			layout,
			keepAlive
		} = oMenu
		const oRouter = {
			path: url,
			component(resolve) {
				// 如果没有component属性说明它是个父节点,则加载模板,否则加载具体页面
				if (!!component) {
					return require([`@/views${component}.vue`], resolve)
				} else {
					return require([`@/components/layout/ParentLayout.vue`], resolve)
				}
			},
			name: name,
			icon: icon,
			hidden: +alwaysShow !== 1,
			meta: {
				layout: layout,
				keepAlive: +keepAlive === 1
			},
			children: !!childrens && childrens.length > 0 ? formatRoutes(childrens) : []
		}
		aRouter.push(oRouter)
	})
	return aRouter
}
页面渲染
// app.vue
<div id="app">
	// 此处component用户切换页面模板
     <component :is="layout">
         <router-view></router-view>
     </component>
 </div>
// ParentLayout.vue
 <div>
 	// 根据路由meta缓存路由
     <keep-alive>
         <router-view v-if="$route.meta.keepAlive"></router-view>
     </keep-alive>
     <router-view v-if="!$route.meta.keepAlive"></router-view>
 </div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值