VueRouter4动态路由,路由守卫,权限控制
1、创建路由实例,定义公共路由router/index.ts
import { createRouter, createWebHashHistory } from "vue-router";
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
// 定义公共页面
export const constantRoutes = [
{
name: 'login',
path: '/login',
component: Login,
meta: {
title:'登录'
}
},
{
name: 'home',
path: '/',
component: Home,
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes,
// 滚动行为,切换页面就置顶
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
})
export default router
2、路由全局使用(main.ts)
import router from './router'
app.use(router)
3、路由守卫(router/permission.ts)
import router from './index'
// 引入进度条
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// 从状态库中取出状态
import useUserStore from '../store/modules/user'
import usePermissionStore from '../store/modules/permission'
NProgress.configure({ showSpinner: false })
// 白名单
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
// 路由守卫
router.beforeEach(async (to, from, next) => {
// 进度条
NProgress.start()
// 具体业务逻辑判断
if (getToken()) {
// 已登录且要跳转的页面是登录页
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else{
// 是否存在token
if (useUserStore().roles.length === 0) {
// 没有拉取用户信息
useUserStore().getInfo().then(() => {
// 获取菜单列表
usePermissionStore().generateRoutes().then((accessRoutes:any):void => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach((route:any) => {
if (!isHttp(route.path)) {
router.addRoute(route) // 动态添加可访问路由表
}
})
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
.catch((error) => {
// 获取用户信息失败 登出并重定向/
useUserStore().logOut().then(() => {
next({ path: '/' })
})
})
} else {
//路由、菜单加载ok
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
//白名单直接跳转
next()
} else {
// 其他菜单跳转值登录界面
next(`/login?redirect=${to.fullPath}`)
NProgress.done()
}
}
})
router.afterEach(() => {
// 关闭进度条
NProgress.done()
})
4、动态路由(router/router-all.ts)
const routerAll = [
{
path:'/layout',
component: () => import('../views/Layout.vue'),
name:"layout",
meta: { title: '菜单管理' },
children:[
{
name: 'xxx',
path: '/',
component:() => import('../views/xxx.vue'),
}
]
}
]
export default routerAll