Vite4 + Vue3 + vue-router4 动态路由
创始人
2024-06-03 15:17:30
0

动态路由,基本上每一个项目都能接触到这个东西,通俗一点就是我们的菜单是根据后端接口返回的数据进行动态生成的。表面上是对菜单的一个展现处理,其实内部就是对router的一个数据处理。这样就可以根据角色权限或者一些业务上的需求,根据不同属性就行路由的划分。到达不同的页面渲染效果。

本文只是讲解菜单的权限控制,不到按钮级别。其实按钮也是差不多的。可以设置一个属性表示菜单,一个属性表示按钮,每一个菜单的叶子节点上都包含根据权限返回的按钮数组。接着可以通过组件的形式去输出相应的按钮就可以。

一、搭建项目 😛😛😛

这里我已经提前搭建好了 Vite4+Pinia2+vue-router4+ElmentPlus搭建Vue3项目(组件、图标等按需引入)

二、根据上面链接搭建好项目,修改src/router/index.ts 😁 😉

asyncRoutes里面可以存放默认的一些路由,比如登录、404、403这些。由于我只是演示,所以就啥都不放了。清晰明朗一点。

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'export const asyncRoutes: RouteRecordRaw[] = []const router = createRouter({history: createWebHashHistory(),routes: asyncRoutes,scrollBehavior: () => ({ left: 0, top: 0 })
})export default router

三、创建 'src/layout/index.vue' 文件 😁 😉

这个文件就是整个项目的布局,一般我们常见的项目都分为上下结构,就如下图。导航和菜单部分基本上是用户登录以后就已经确定好了,点击菜单的时候去切换路由。我这里由于这部分不是重点,所以我就很潦草的画了一个很简单的页面。


四、创建 '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?: Array
}type RouterType = RouteRecordRaw & {hidden?: boolean;alwaysShow?: boolean;
}export interface IPermissionState {routes: RouterType[]dynamicRoutes: RouterType[]menus: Array
}function hasPermission(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 (hasPermission(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

七、src/views下的两个home文件进行一下修改

home 这两个文件不修改也不影响。


home1 这两个文件不修改也不影响。

八、效果浏览

我是Etc.End。如果文章对你有所帮助,记得帮我点个免费的赞和收藏。同时欢迎各位小伙伴一起学习,一起成长👉👉WX:SH--TS。🍓 🍑 🍈 🍌 🍐 🍍 🍠 🍆 🍅 🌽 

相关内容

热门资讯

离开旧爱,想坐慢车,看透彻了心... 离开旧爱,想坐慢车,看透彻了心就会是晴朗的 是哪首歌?分手快乐,梁静茹的一首老歌分手快乐 梁静茹 我...
火影忍者决斗场什么忍者能卡进墙... 火影忍者决斗场什么忍者能卡进墙里波风水门。1、利用瞬身术进竖核入墙内:首先选信尘择一个合适的墙壁,然...
只有再爱一次,才能忘记前男友吗... 只有再爱一次,才能忘记前男友吗?你可以多和你的好朋友谈心啊,多结交一些朋友一样可以让你淡忘他,不一定...
女的穿越时空回到古代朝鲜的言情... 女的穿越时空回到古代朝鲜的言情小说古灵的《替身》
求一部动漫,很久以前看的,忘记... 求一部动漫,很久以前看的,忘记了名字。是关于一个少女变身用扑克牌行窃的故事。圣少女(提醒:变身后穿黑...
好听的歌 劲爆的 伤感的 忧伤... 好听的歌 劲爆的 伤感的 忧伤的 都行求要听的 欢快 忧伤的都行 只要好听 分享下呗Gee-少...
汤圆创作里面容易签约嘛?难度怎... 汤圆创作里面容易签约嘛?难度怎么样?是特别好看的文文才会成功嘛?什么地方,没听说过。
异界小说 男主被冰封了 然后有... 异界小说 男主被冰封了 然后有一帮来拍电影的女的在洗澡的时候发现了他! 好像是这样的就记得这些还有点...
选择词语填在横线上(快来帮帮我... 选择词语填在横线上(快来帮帮我吧)调整 整顿 矗立 伫立1、调整 整顿2、耸立 伫立调整 整顿矗立...
朴灿烈香水百瑞德,灿烈用的是百... 朴灿烈香水百瑞德,灿烈用的是百瑞德哪种香味的香水?朴灿烈喜欢用的百瑞德香水是银色山泉这款,这款香水是...
精神分析的学习与自我成长的联系... 精神分析的学习与自我成长的联系?心理学专业人士来答卡伦 霍尼《神经症与人的成长》,如果你是专业的,你...
怎么就没一首我喜欢听的歌 怎么就没一首我喜欢听的歌你最喜欢听的歌,听久了也会腻。心情不要那么浮躁,就会找到你喜欢的那首歌
如果把地球直线挖通的话,人跳进... 如果把地球直线挖通的话,人跳进去会摔死还是会掉到另一端呢?应该会直接摔死,因为地球中心才是非常复杂的...
和男朋友分手,他居然说谢谢我给... 和男朋友分手,他居然说谢谢我给他上了一堂人生课,什么意思?虽然你们分手了,但是你们一起度过了一段人生...
带口哨的纯音乐 带口哨的纯音乐曲名:The Voyage艺人:The Mountaineering Club Orc...
禾葡兰的禾善基金的理念是什么? 禾葡兰的禾善基金的理念是什么?禾善基金是有什么理念呢?禾善基金是禾葡兰创办的互助基金会,基金会的救助...
名侦探柯南给工藤新一的挑战书每... 名侦探柯南给工藤新一的挑战书每集开头那段音乐,有完整的吗,不是剧场和动画那个!那首歌是仓木麻衣的《T...
路漫漫其修远兮的下一句 路漫漫其修远兮的下一句路漫漫其修远兮,吾将上下而求索”这句出自屈原的名作《离骚》。“路漫漫其修远兮,...
海伦凯勒的背景 海伦凯勒的背景 海伦·凯勒(Helen Keller)(1880年6月27日-1968年6月1日...
激情燃烧的岁月实际上就是中国人... 激情燃烧的岁月实际上就是中国人焕发出巨大的劳动热情2.咱们工人有力量的歌曲,焕发的是现代人的激情。以...