### Vue3 + Vite + Pinia 后台管理系统中 vue-router 的封装示例
在构建基于 Vue3 和 Vite 的后台管理系统时,`vue-router` 的封装是一个关键步骤。通过封装路由,可以实现动态路由加载、权限校验、路由拦截等功能。以下是一个完整的 `vue-router` 封装示例。
#### 1. 路由配置文件结构
通常将路由配置文件存放在 `src/router` 目录下。以下是目录结构的示例:
```
src/
├── router/
│ ├── index.js // 路由入口
│ ├── routes.js // 路由定义
│ ├── guards.js // 路由守卫
│ └── dynamicRoutes.js // 动态路由
```
#### 2. 路由定义 (`routes.js`)
在 `routes.js` 中定义静态路由和动态路由的模板。
```javascript
// src/router/routes.js
export const constantRoutes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/Login.vue'),
meta: { title: '登录', hidden: true },
},
{
path: '/',
redirect: '/dashboard',
component: () => import('@/layouts/index.vue'),
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index.vue'),
meta: { title: '仪表盘', icon: 'dashboard', roles: ['admin', 'editor'] },
},
],
},
];
export const asyncRoutes = [
{
path: '/system',
name: 'System',
component: () => import('@/layouts/index.vue'),
meta: { title: '系统管理', icon: 'setting', roles: ['admin'] },
children: [
{
path: 'user',
name: 'User',
component: () => import('@/views/system/user/index.vue'),
meta: { title: '用户管理', icon: 'user' },
},
{
path: 'role',
name: 'Role',
component: () => import('@/views/system/role/index.vue'),
meta: { title: '角色管理', icon: 'team' },
},
],
},
];
```
#### 3. 路由初始化与动态加载 (`index.js`)
在 `index.js` 中初始化路由,并实现动态路由加载功能。
```javascript
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import { constantRoutes, asyncRoutes } from './routes';
import { filterAsyncRoutes } from './dynamicRoutes';
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
});
// 动态添加路由
export function setupRoutes(store) {
return new Promise((resolve) => {
if (store.getters.isAddRouters) {
resolve();
} else {
const accessedRoutes = filterAsyncRoutes(asyncRoutes, store.getters.roles);
accessedRoutes.forEach((route) => {
router.addRoute(route);
});
store.commit('SET_IS_ADD_ROUTERS', true);
resolve();
}
});
}
export default router;
```
#### 4. 动态路由过滤 (`dynamicRoutes.js`)
根据用户权限过滤动态路由。
```javascript
// src/router/dynamicRoutes.js
export function filterAsyncRoutes(routes, roles) {
const res = [];
routes.forEach((route) => {
const tmp = { ...route };
if (hasPermission(tmp.meta?.roles, roles)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles);
}
res.push(tmp);
}
});
return res;
function hasPermission(roles, userRoles) {
if (!roles || roles.length === 0) return true;
return roles.some((role) => userRoles.includes(role));
}
}
```
#### 5. 路由守卫 (`guards.js`)
实现全局前置守卫,用于权限校验和页面跳转。
```javascript
// src/router/guards.js
import router from './index';
import store from '@/store';
router.beforeEach(async (to, from, next) => {
const token = store.getters.token;
if (to.path === '/login') {
if (!token) {
next();
} else {
next({ path: '/' });
}
} else {
if (token) {
if (!store.getters.roles.length) {
await store.dispatch('GetInfo');
await setupRoutes(store); // 动态加载路由
}
next();
} else {
next({ path: '/login', query: { redirect: to.fullPath } });
}
}
});
```
#### 6. 在主应用中注册路由
在 `main.ts` 或 `main.js` 中引入并使用路由模块。
```javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
const app = createApp(App);
app.use(router).use(store).mount('#app');
```
#### 7. 示例代码片段
以下是封装后的路由组件使用示例:
```vue
<!-- src/App.vue -->
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App',
};
</script>
```
---
###