1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue3动态路由及菜单

vue3动态路由及菜单

时间:2020-12-30 21:34:37

相关推荐

vue3动态路由及菜单

一般来说,前端项目中的路由,很有可能是需要动态注册的。因为菜单可能在管理系统中维护,还跟权限绑定,用户登录以后,需要动态展示菜单。菜单往往跟路由挂钩,因此,路由需要动态注册。

具体如何实现呢?思路是,系统只提供默认的路由,登录以后,读入菜单/路由数据,加载。这其中,可能会出现默认路由与动态路由有重叠的情况。处理办法是覆盖。数据结构方面,菜单与路由数据二合一。

一、项目结构

这是我们一个项目的公共框架的代码结构。我们打算在src/modules/存放具体业务系统的代码,而外部是相对稳定,可以复用的框架代码。

二、默认路由

src/router/default.js,内容比较少,只有登录、首页、404三个。其余全都靠动态注册。

路由项中,自定义属性放在meta里。动态路由与默认路由的数据结构一致。

/*** 默认路由* 具体业务路由,应在src/modules/router里定义,或者从后端动态加载*/export default [/*** 路由项结构:*{path: "/",//路径,(必选;path、name、component是路由规定必选的元素)也可以带参数,如 path: "/resource/detail/:id",name: "路由名称,是路由唯一标识",(必选)component: 指向组件,如 Home,或者() => import("../views/login/PageIndex.vue"),(必选)meta: {//meta里的属性可以自定义,全部为可选项text: "名称",//展示在菜单里,(可选)navi: true, //导航条(一级菜单),(可选)noLogin: true, //无须登录即可浏览,(可选)access: "work:sysmanage,work:resourcemanage",//权限标识,(可选)},children: [],},*/{path: "/login",name: "login",component: () => import("../views/login/PageIndex.vue"),meta: {noLogin: true, //无须登录即可浏览},},{path: "/",name: "Home",component: () => import("../views/PageIndex.vue"),},{path: "/notAllow",name: "notAllow",component: () => import("../views/sys/notAllow.vue"),},];export const HomeName = "Home";

三、动态注册

注册的时机是什么?在哪里注册?怎么注册?

答曰:登录之后注册;在路由守卫里注册;用router.addRoute()一个个加进去。

1、登录之后进行注册,在路由卫士里注册

所谓路由守卫,就是路由规则。这名字我是从网上抄过来的。

src/router/index.js

import {createRouter, createWebHashHistory } from "vue-router";import routes from "./default";import routeAssembler from "./setup";import {hasAuthority } from "@/utils/login.js";const router = createRouter({history: createWebHashHistory(),routes,});// 路由守卫let registerRouteFresh = true;//是否还没有动态加载过router.beforeEach((to, from, next) => {const isLogin = localStorage.isLogin ? true : false;if (isLogin) {//已登录情况下验证权限let isAccess = hasAuthority(to.meta.access);if (!isAccess) {//没有权限next("/notAllow");return;}if (registerRouteFresh) {//还没有动态加载过//动态注册路由 <----------------------------------------routeAssembler(router);registerRouteFresh = false;next({...to, replace: true });} else {//已经登录了,不能再打开登录页to.path === "/login" ? next("home") : next();}} else {//如果无须登录则直接打开,否则转向登录页面to.meta.noLogin || to.path === "/login" ? next() : next("/login");}});export default router;

2、如何动态注册

src/router/setup.js,即上面例子中的routeAssembler:

/*装配路由及菜单*/import fixItems from "./default"; //默认路由import {HomeName } from "./default"; //统一命名首页路由项(参考前面的默认路由)import projectItems from "@/modules/router"; //具体业务系统的路由export default (router) => {//获得动态路由const dynaItems = getDynamicItems();//对齐首页(统一命名首页)adpatHome(HomeName, dynaItems);//添加动态路由dynaItems.forEach((value) => {router.addRoute(value);});};const getDynamicItems = () => {/*获取动态路由,从指定文件加载或从后端获取*/return projectItems;};//默认路由与业务路由对齐首页的路由信息//所谓对齐,就是大家的name保持一致,这样才能保证动态加入的路由项,覆盖掉前面的path和name相同的路由const adpatHome = (HomeName, dynaItems) => {let home = dynaItems.filter((item) => {return item.path === "/";});if (home.length > 0 && home[0].name !== HomeName) {/*** 如果业务路由定义了首页,但其name与默认路由首页的name不相同* 则将业务路由中首页项的name置为默认名称* 因为按照vue-router的规则,addRoute的时候,如果存在同名同路径的路由项,则覆盖之* 我们要的就是覆盖默认,以业务路由设置为准*/home[0].name = HomeName;}};

这里面有个如果动态路由,与默认路由中存在相同的路由项,该如何处理的问题。

按照vue3的router规则,如果后面加进来的路由项,仅仅是path相同,而name不同,则不算是相同的路由项,addRoute()进去之后,仍然是原先的路由项起作用;但如果是path和name都相同,则原先的会被覆盖(我怀疑是name相同就会被覆盖)。所以,默认路由中有首页路由,指向框架代码中的默认首页;加载动态路由后,该路由被覆盖,指向了具体业务系统的首页。这也表明,我们无须自己手动删除已加载的同名路由项。事实上,删除还会报错。

相关文章:

不依赖框架用vue3空白项目从头打造一个过得去的前端

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。