医药平台网站建设,龙华网站建设网站设计公司,推进网站建设,logo免费网站动态路由#xff0c;基本上每一个项目都能接触到这个东西#xff0c;通俗一点就是我们的菜单是根据后端接口返回的数据进行动态生成的。表面上是对菜单的一个展现处理#xff0c;其实内部就是对router的一个数据处理。这样就可以根据角色权限或者一些业务上的需求#xff0…动态路由基本上每一个项目都能接触到这个东西通俗一点就是我们的菜单是根据后端接口返回的数据进行动态生成的。表面上是对菜单的一个展现处理其实内部就是对router的一个数据处理。这样就可以根据角色权限或者一些业务上的需求根据不同属性就行路由的划分。到达不同的页面渲染效果。
本文只是讲解菜单的权限控制不到按钮级别。其实按钮也是差不多的。可以设置一个属性表示菜单一个属性表示按钮每一个菜单的叶子节点上都包含根据权限返回的按钮数组。接着可以通过组件的形式去输出相应的按钮就可以。
一、搭建项目
这里我已经提前搭建好了 Vite4Pinia2vue-router4ElmentPlus搭建Vue3项目(组件、图标等按需引入)
二、根据上面链接搭建好项目修改src/router/index.ts
asyncRoutes里面可以存放默认的一些路由比如登录、404、403这些。由于我只是演示所以就啥都不放了。清晰明朗一点。
import { createRouter, createWebHashHistory, RouteRecordRaw } from vue-routerexport const asyncRoutes: RouteRecordRaw[] []const router createRouter({history: createWebHashHistory(),routes: asyncRoutes,scrollBehavior: () ({ left: 0, top: 0 })
})export default router三、创建 src/layout/index.vue 文件
这个文件就是整个项目的布局一般我们常见的项目都分为上下结构就如下图。导航和菜单部分基本上是用户登录以后就已经确定好了点击菜单的时候去切换路由。我这里由于这部分不是重点所以我就很潦草的画了一个很简单的页面。 templatediv stylepadding: 100px;divdiv v-for(item, index) in menus[0].children :keyindex stylemargin-bottom: 20px;router-link :toitem.path{{item.title}}/router-link/div/divdivrouter-view #default{route, Component}transition leave-from-classts-web-fade--leave-to enter-active-classanimate__animated animate__bounceInRightcomponent :isComponent/component/transition/router-view/div/div
/templatescript langts
import appStore from /pinia;export default defineComponent({setup() {const { menus } appStore.permissionModuleconsole.log(menus, menus)return {menus,}}
})
/script四、创建 src/pinia/modules/permission.ts 文件
由于我这里是一个demo没有真正的去接入后端。所以我暂时放入的静态数据。自己替换成接口返回就好。
import { defineStore } from pinia;
import router from /router
// 这是整个项目的布局页面。根据自己的项目替换就好
import Layout from /layout/index.vue;
import {RouteRecordRaw} from vue-router;export type MenuType {path: string,title: string,component: string,redirect?: string,children?: ArrayMenuType
}type RouterType RouteRecordRaw {hidden?: boolean;alwaysShow?: boolean;
}export interface IPermissionState {routes: RouterType[]dynamicRoutes: RouterType[]menus: ArrayMenuType
}function hasPermissionT(roles: T[], route: RouterType) {if (route.meta route.meta.roles) {return roles.some((role) (route.meta?.roles as T[]).includes(role));}return true
}const modules import.meta.glob(../../views/**/*.vue)
const _import (path: string) () import(../../views/${path}.vue)const assembleRouter (routers: any) {const addRouter routers.filter((router: any) {(router.title router.icon) (router.meta {title: router.title,// icon: router.icon,// alwaysShow: router.alwaysShow || false,// affix: router.affix || false,})if (router.component Layout) {router.component shallowRef(Layout)} else {if (import.meta.env.MODE development) {router.component _import(router.component)} else {router.component modules[../../views/${router.component}.vue]}}if (router.children router.children.length) {router.children assembleRouter(router.children)}return true})return addRouter
}export function filterAsyncRoutes(routes: RouterType[], roles: string[]) {const res: RouterType[] []routes.forEach((route) {const tmp { ...route }if (hasPermissionstring(roles, tmp)) {if (tmp.children) {tmp.children filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
}export const permissionModule defineStore({id: permission,state(): IPermissionState{return {routes: [],dynamicRoutes: [],menus: []}},actions:{async getMenus() {try {// 这里由于不方便演示所以我写的静态数据。换着自己对于的接口就好const list:MenuType[] [{path: /,title: ts-super-web,component: Layout,redirect: /home,children: [{title: home,path: home,component: home},{title: home1,path: home1,component: home1}]}]this.menus list// 组件路由let addRouter assembleRouter(this.menus)// addRouter assembleRouterDelete(addRouter)// 动态添加菜单addRouter.forEach((ts: any) {router.addRoute(ts)})} catch (err) {return Promise.reject(err);}}}
})五、路由拦截器
因为上面说到我没有真正的接入后端所以这里我也没有进行token判断。自行增加一下就好比较简单。除了token还可以在拦截器里面放置一个白名单列表对于白名单里面的路由我们不做拦截。比如login登录页面、404等等。根据自己需求配置就好。
import router from /router
// ts-ignore
import NProgress from nprogress
import nprogress/nprogress.css
import appStore from /pinia;NProgress.configure({easing: ease, // 动画方式showSpinner: true, // 是否显示加载icotrickleSpeed: 200, // 自动递增间隔minimum: 0.4, // 更改启动时使用的最小百分比
})router.beforeEach(async (to, form, next) {// 这里处理自己的逻辑,比如需要登录以后才能访问其他页面等等NProgress.start()const { menus, getMenus } appStore.permissionModuleif (menus.length 0) {try {// 调用接口获取菜单 进行跳转await getMenus()next({ ...to, replace: true })} catch (err) {next()}} else {next()}NProgress.done()
})六、修改app.vue
templaterouter-view /
/templatestyle
html,body,#app {height: 100%;width: 100%;margin: 0;padding: 0;
}
/style
七、src/views下的两个home文件进行一下修改
home 这两个文件不修改也不影响。
templatep stylefont-size: 32px;你好我是home/p
/templatehome1 这两个文件不修改也不影响。
templatep stylefont-size: 32px;你好我是home1/p
/template
八、效果浏览 我是Etc.End。如果文章对你有所帮助记得帮我点个免费的赞和收藏。同时欢迎各位小伙伴一起学习一起成长WX:SH--TS。