在后臺管理系統中,前端的路由往往需要根據用戶的權限動態生成。這篇文章將重點介紹如何在 Vue 3 中實現動態路由注冊和手動導航,確保用戶訪問的頁面與權限對應。
1. 動態路由的需求與原理
為什么需要動態路由?
- 權限控制:不同用戶角色需要看到不同的菜單和頁面。
- 后端驅動:后端返回菜單數據,前端動態渲染菜單和注冊路由。
- 避免硬編碼:路由不再寫死在前端代碼里,保證靈活性。
- 動態注冊路由:根據后端返回的數據,通過router.addRoute動態添加到路由系統。
- 手動導航:添加新路由后,需要手動觸發導航保證路由生效。
靜態路由是所有用戶共享的基本路由,如登錄頁、404頁等。import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import Layout from '@/layout/admin.vue';
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: Layout,
name: 'admin',
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/index.vue'),
meta: { title: '登錄頁' },
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/pages/404/index.vue'),
meta: { title: '404' },
},
];
const asyncRoutes: Array<RouteRecordRaw> = [
{
path: '/',
name: '/',
component: () => import('@/pages/index/index.vue'),
meta: { title: '首頁' },
},
{
path: '/goods/list',
name: '/goods/list',
component: () => import('@/pages/goods/list.vue'),
meta: { title: '商品列表' },
},
{
path: '/category/list',
name: '/category/list',
component: () => import('@/pages/category/list.vue'),
meta: { title: '分類列表' },
},
];
該方法接收后端返回的菜單數組,并將匹配的動態路由添加到主路由admin下。import { router } from '@/router/index';
export const addRoutes = (routesArray: Array<MenusArray>) => {
let hasNewRoutes = false;
const addRoutesFromMenus = (menus: Array<MenusArray>) => {
menus.forEach((menu) => {
const route = asyncRoutes.find((r) => r.path === menu.frontpath);
// 添加到router中
if (route && !router.hasRoute(route.path)) {
router.addRoute('admin', route);
hasNewRoutes = true;
}
// 遞歸處理子菜單
if (menu.child && menu.child.length > 0) {
addRoutesFromMenus(menu.child);
}
});
};
addRoutesFromMenus(routesArray);
return hasNewRoutes;
};
- router.addRoute:VueRouter提供的API,可以動態添加路由。
- 避免重復添加:router.hasRoute檢查路由是否已存在,防止重復注冊。
- 遞歸處理:支持多級菜單,遞歸遍歷child子菜單。
在router.beforeEach路由守衛中,調用addRoutes注冊動態路由,并實現手動導航。import { getToken } from '@/utils/auth';
import store from '@/store';
import { addRoutes } from '@/router/index';
router.beforeEach(async (to, from, next) => {
const token = getToken();
let hasNewRoutes = false;
// 顯示全局加載狀態
showFullLoading();
// 未登錄跳轉到登錄頁
if (!token && to.name !== 'login' && to.name !== 'NotFound') {
return next('/login');
}
// 已登錄訪問登錄頁,重定向到主頁
if (token && to.name === 'login') {
return next('/');
}
// 已登錄狀態下,動態添加路由
if (token) {
await store.dispatch('user/getUserInfo'); // 拉取用戶信息
hasNewRoutes = addRoutes(store.getters['menu/getMenus']); // 添加動態路由
}
// 設置頁面標題
if (to.meta.title) {
document.title = `${to.meta.title}-測試后臺管理`;
} else {
document.title = '測試后臺管理';
}
// 手動導航:如果添加了新路由,重新跳轉當前頁面
hasNewRoutes ? next(to.fullPath) : next();
});
- router.addRoute是動態操作,添加新路由后需要重新跳轉一次,確保用戶能正常訪問新注冊的頁面。
- next(to.fullPath):手動跳轉到當前頁面。
- 動態注冊路由:調用
addRoutes
將菜單數據匹配的路由添加到 admin
下。 - 手動導航:動態路由添加完成后,使用
next(to.fullPath)
手動觸發頁面跳轉。
- 動態路由:后端驅動,通過
addRoutes
動態注冊。 - 靈活性:動態路由使前端代碼更靈活,后端控制權限更方便。
閱讀原文:原文鏈接
該文章在 2024/12/30 16:01:11 編輯過