基本配置
import { createRouter, createWebHistory } from 'vue-router';
import pinia from './pinia';
import { useUserStore } from '../store/user';
const user = useUserStore(pinia);
// 不需要权限的页面
const constantRoutes = [
{
// 登录
path: '/login',
name: 'login',
component: () => import('../views/login/index.vue')
},
{
// 404
path: '/:pathMatch(.*)',
name: 'notFound',
component: () => import('../views/error/notFound.vue')
},
{
// 无权限
path: '/noPermission',
name: 'noPermission',
component: () => import('../views/error/noPermission.vue')
}
];
const asyncRoutes = {
path: '/',
name: 'main',
component: () => import('../views/mainPage.vue'),
children: [
{
// 首页
path: '/',
name: 'home',
component: () => import('../views/home/index.vue')
},
{
// 用户管理
path: '/settingUser',
name: 'settingUser',
component: () => import('../views/setting/user.vue')
}
]
};
const router = createRouter({
history: createWebHistory('/'),
routes: constantRoutes
});
router.addRoute(asyncRoutes);
router.beforeEach((to, from, next) => {
// 切换router时,取消pending中的请求
if (window.__axiosPromiseArr) {
window.__axiosPromiseArr.forEach((ele, ind) => {
ele.cancel();
delete window.__axiosPromiseArr[ind];
});
}
// token过期
if (localStorage.getItem('expires') && (new Date().getTime() - localStorage.getItem('expires')) / 1000 > 1) {
this.$message.error('登录失效,请重新登录', () => {
localStorage.removeItem('userInfon');
localStorage.removeItem('token');
localStorage.removeItem('expires');
location.href = '/login';
});
return;
}
// 登录判断
if (user.token) {
if (to.path === '/login') {
next({ path: '/' });
} else {
// 权限判断
next();
}
} else {
if (to.path === '/login') {
next();
} else {
next({ name: 'login' });
}
}
});
// 跳转完成后,将滚动条位置重置
router.afterEach(to => {
window.scrollTo(0, 0);
});
export default router;
1.安装 vue-router
npm install vue-router
2.路由实例
创建路由实例,顺带初始化静态路由,而动态路由需要用户登录,根据用户拥有的角色进行权限校验后进行初始化。
// src/router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
export const Layout = () => import('@/layout/index.vue');
// 静态路由
export const constantRoutes: RouteRecordRaw[] = [
{
path: '/redirect',
component: Layout,
meta: { hidden: true },
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index.vue')
}
]
},
{
path: '/login',
component: () => import('@/views/login/index.vue'),
meta: { hidden: true }
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index.vue'),
name: 'Dashboard',
meta: { title: 'dashboard', icon: 'homepage', affix: true }
}
]
}
];
/**
* 创建路由
*/
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes as RouteRecordRaw[],
// 刷新时,滚动条位置还原
scrollBehavior: () => ({ left: 0, top: 0 })
});
/**
* 重置路由
*/
export function resetRouter() {
router.replace({ path: '/login' });
location.reload();
}
export default router;
3.全局注册路由实例
// main.ts
import router from "@/router";
app.use(router).mount('#app')
4.动态权限路由
路由守卫 src/permission.ts
,获取当前登录用户的角色信息进行动态路由的初始化
最终调用 permissionStore.generateRoutes(roles)
方法生成动态路由
// src/store/modules/permission.ts
import { listRoutes } from '@/api/menu';
export const usePermissionStore = defineStore('permission', () => {
const routes = ref<RouteRecordRaw[]>([]);
function setRoutes(newRoutes: RouteRecordRaw[]) {
routes.value = constantRoutes.concat(newRoutes);
}
/**
* 生成动态路由
*
* @param roles 用户角色集合
* @returns
*/
function generateRoutes(roles: string[]) {
return new Promise<RouteRecordRaw[]>((resolve, reject) => {
// 接口获取所有路由
listRoutes()
.then(({ data: asyncRoutes }) => {
// 根据角色获取有访问权限的路由
const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
setRoutes(accessedRoutes);
resolve(accessedRoutes);
})
.catch(error => {
reject(error);
});
});
}
// 导出 store 的动态路由数据 routes
return { routes, setRoutes, generateRoutes };
});
接口获取得到的路由数据
根据路由数据 (routes)生成菜单的关键代码
src/layout/componets/Sidebar/index.vue | src/layout/componets/Sidebar/SidebarItem.vue |
---|---|