1.添加组件vue-router
yarn add vue-router
2.动态路由添加
创建文件/router/index.ts
import { createRouter, createWebHashHistory, RouteLocationNormalized, RouteRecordRaw } from 'vue-router';
import { Session } from '@/utils/storage';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { HOME_NAME,LOGIN_PATH } from '@/utils/constant';
import { useMenuStore } from '@/stores/menu';
import staticRoutes from './static';
const router = createRouter({
history: createWebHashHistory(),
routes: [...staticRoutes],
});
async function canUserAccess(_to:RouteLocationNormalized){
const token = Session.get('token');
return !!token;
}
/**
* 动态添加路由
* @param {*} parentName
* @param {*} menus
*/
const addRoutes = (parentName: string,menus: MenuInfo[] = [])=> {
const parentRouter: RouteRecordRaw = {path: '',name: parentName,children:[]};
menu2Routes( parentRouter, menus);
const pr = router.getRoutes().find(v=>v.name== parentName);
if(pr){
pr.children = parentRouter.children;
router.addRoute(pr);
}
}
/**
* 菜单转路由列表
* @param {*} parentRouter
* @param {*} menus
*/
const menu2Routes = (parentRouter: RouteRecordRaw, menus: MenuInfo[] = [])=>{
menus.forEach((info)=>{
const newRouter = {
path: info.path,
name: info.name,
children:[],
meta:{title: info.title}
};
if(info.children && info.children.length==0){
newRouter.component =()=>import(`/src/views/modules${ info.path }/index.vue`);
}
parentRouter?.children?.push( newRouter );
if(info.children && info.children.length>0){
menu2Routes(newRouter, info.children);
}
});
}
/**
* 扩展router,添加刷新路由方法
*/
router.refreshRouters=()=>{
//解决刷新界面路由重置问题
const useMenu = useMenuStore();
//将菜单路由挂载到HOME_NAME静态路由下
addRoutes(HOME_NAME, useMenu.menus);
return router;
}
router.beforeEach(async (to, _from) => {
NProgress.configure({showSpinner: false});
NProgress.start();
const canAccess = await canUserAccess(to);
if (!canAccess && to.path !=LOGIN_PATH) return LOGIN_PATH;
})
router.afterEach((_to, _from, _failure) => {
NProgress.done()
})
// 添加异常处理
const originalPush = router.push
router.push = (to) => {
try {
return originalPush(to)
} catch (error) {
window.console.log(`%c${ error }`, 'color:red')
return originalPush({ name: '404' })
}
}
// 导出路由
export default router;
静态路由文件/router/static.ts
import { RouteRecordRaw } from 'vue-router';
import { HOME_NAME,HOME_PATH, LOGIN_NAME,LOGIN_PATH,MENU_DEFAULT_ACTIVE } from '@/utils/constant';
const staticRoutes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: MENU_DEFAULT_ACTIVE,
},
{
path: HOME_PATH,
name: HOME_NAME,
component: () => import('@/views/home/index.vue'),
meta: {
title: '主页',
},
children:[],
},
{
path: LOGIN_PATH,
name: LOGIN_NAME,
component: () => import('@/views/login/index.vue'),
meta: {
title: '登录',
},
},
{
path: '/:path(.*)*',
name: 'notFound',
component: () => import('@/views/error/404.vue'),
meta: {
title: '找不到此页面',
},
},
{
path: '/401',
name: 'noPermission',
component: () => import('@/views/error/401.vue'),
meta: {
title: '没有权限',
},
},
];
export default staticRoutes;
3.使用动态路由
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus';
import router from '@/router'
import i18n from '@/locale'
import 'element-plus/dist/index.css';
import './style.css'
const app = createApp(App)
//添加动态路由使用
//refreshRouters --解决刷新界面路由重置问题
app.use(router.refreshRouters());
app.use(i18n.loadDefault());
app.use(ElementPlus);
app.mount('#app')
4.添加面包屑
mkdir -p src\\views\\home\\components\\headbar\\components\\crumb
crumb目录下创建文件index.ts
<template>
<el-breadcrumb separator="/" class="crumb-container flex">
<transition-group name="right-in-out">
<el-breadcrumb-item
v-for="item in crumbs"
:key="item.name">
{{ item.meta?.title }}
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script setup lang="ts">
import {ref,watchEffect} from "vue"
import { useRoute, RouteRecordRaw } from 'vue-router'
const crumbs = ref<RouteRecordRaw[]>([]);
const route = useRoute();
const crumbHandle = ()=>{
crumbs.value = []
//读取路由信息
route.matched.forEach((item) => {
crumbs.value.push(item);
});
//因为是挂载主页路由下,所以去掉根节点
crumbs.value.shift();
}
watchEffect(() => {
crumbHandle()
})
</script>
<style lang="scss" scoped>
:deep(.el-breadcrumb__inner) {
font-weight:bolder;
}
</style>
5.效果