import{SideBar,AppMain,NavBar}from'./components/index.ts';其中AppMain/index.vue这里加了动画与组件缓存,后续会根据后端返回的catch字段进行缓存控制
在api/menu/index.ts中配置调用获取路由及权限的接口
这里什么都不用传
新建store/index.ts目录用来存放全局数据,菜单列表数据,权限列表数据,以及是否折叠菜单等等,同时调用getInfo接口获取数据
import{defineStore}from'pinia';import{getInfo}from'../api/menu/index';import{AppStoreState}from'./types';exportdefaultdefineStore('appStore',{state:():AppStoreState=>{return{menuList:[],isCollapse:false,permissions:[],};},actions:{asyncgetInfo(){const{data}=awaitgetInfo({});this.menuList=data.routers;this.permissions=data.permissions;},},});其中AppStoreState
我们可以通过router.addRoute方式动态添加子路由,这里我们需要根据后端返回的组件component字段来创建目录,比如system/role/index就在views目录下新建system/role/index.vue
角色管理
同样的
这些用于后续测试
添加之前需要将后端返回的菜单列表数据转换为符合Vue路由的格式,因为后端返回的组件路径是个字符串,VueRouter的component是不能直接使用的,这里我们在utils文件夹新建filterRouters.ts,
//匹配views里面所有的.vue文件constmodules=import.meta.glob('../views/**/*.vue');//将本地的路由与后端返回的路由进行匹配exportconstloadView=(view:any)=>{letres;for(constpathinmodules){constdir=path.split('views/')[1].split('.vue')[0];if(dir===view){res=()=>modules[path]();}}returnres;};exportconstfilterRoute=(data:any)=>{data.forEach((item:any)=>{if(item.children.length>0){deleteitem.component;filterRoute(item.children);}else{item.component=loadView(item.component);//item.redirect='/404';}});returndata;};然后再新建hooks/useHandleRouter.ts,进行动态添加路由的逻辑
最后在router/index引入使用,同时添加一个/404的路由,当用户访问的路由不存在时,会跳转到/404路由
import{createRouter,createWebHashHistory,RouteRecordRaw}from'vue-router';import{useHandleRouter}from'@/hooks/useHandleRouter';exportconstroutes:RouteRecordRaw[]=[{path:'/',name:'Index',redirect:'/index',component:()=>import(/*webpackChunkName:'index'*/'@/layout/index.vue'),children:[{path:'/index',component:()=>import('@/views/index.vue'),name:'Home',meta:{title:'首页'},},],},{path:'/login',name:'Login',component:()=>import(/*webpackChunkName:'login'*/'@/views/login/index.vue'),},{path:'/:pathMatch(.*)*',component:()=>import('@/views/error/404.vue'),},];constrouter=createRouter({history:createWebHashHistory(),scrollBehavior(_to,_from,savedPosition){if(savedPosition){returnsavedPosition;}else{return{top:0};}},routes,});useHandleRouter(router);exportdefaultrouter;到这里我们便完成了路由的动态加载
接下来我们来完成菜单侧边栏(SideBar)部分,这里我们使用element-plus中的菜单组件el-menu,然后通过判断后端返回的路由类型是菜单还是目录来分别使用el-menu-item和el-menu-sub。
新建layout/SideBar/index.vue来编写侧边栏的代码
其中SideBarItem组件用于判断路由类型是菜单还是目录,然后渲染对应的组件。
除此之外,SideBarItem组件中引入了自身SideBarItem实现了组件的递归,这样就可以保证无论菜单层级多少都可以对应展示