vue3项目中实现动态路由

时间:2024-12-18 07:35:04

完成效果

 
  1. 1.登录----根据用户登录获取当前用户的菜单
  2. 2.开始发送ajax 获取菜单
  3. 3.菜单解析为路由相关配置
  4. 4.添加到路由配置当中
  5. 5.动态路由实现完成

第一步:配置静态路由

 
//
import { createApp } from "vue";
import "./";
import App from "./";
import "element-plus/theme-chalk/";
//导入
import router from "./router/index";
//将路由关联到vue3 项目
createApp(App).use(router).mount("#app");
 
路由模块文件

import { createRouter, createWebHistory } from "vue-router";

import routes from "./routes";

const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savePosiation) {
if (savePosiation) {
return savePosiation;
}
return { left: 0, top: 0 };
},
});

export default router;

//静态路由配置文件
//路由配置
//引入组件
import Index from "@/views/";
import Login from "@/views/";
import NotFound from "@/views/";

export default [
{
path: "/",
component: Index,
name: "admin",
},
{
path: "/login",
component: Login,
},
{
path: "/not-found",
component: NotFound,
},
{
path: "/:pathMatch(.*)*", //vue2 * vue3 改为正则
redirect: "/not-found",
},
];

第二步实现登录和安全守卫

 
//守卫
let whiteList = ["/login", "/not-found"];
((to, from) => {
//读取token
let token = ("_token");

//未登录
if (!token) {
if (() == -1) {
return { path: "/login" };
}
} else {
if ( == "/login") {
return { path: "/" };
}
}
});

第三步:发送请求获取用户动态菜单

 
1.获取用户菜单接口
//用户模块

import { get } from "../utils/request";

//获取用户菜单
export const getUserMenu = () => {
return get("/getRouters");
};
 
2.在守卫中发送请求获取menu
//守卫
let whiteList = ["/login", "/not-found"];
//定义菜单
let Menu: any = null;
(async (to, from) => {
//读取token
let token = ("_token");

//未登录
if (!token) {
if (() == -1) {
return { path: "/login" };
}
} else {
if ( == "/login") {
return { path: "/" };
}
//能检测到登录完成
if (!Menu) {
//发送请求
let res = await getUserMenu();
();
}
}
});

 
3.封装一个递归方法解析菜单
//解析菜单
function CompilerMenu(arr: Array<any>) {
if (!) {
return;
}
((item) => {
//定义对象
let rts = {
name: ,
path: ,
meta: ,
component: ,
};
//如果存在子集进行递归解析
if ( && ) {
CompilerMenu();
}
(rts);
});

 
4.针对解析的数据 进行组件懒加载
vite工具
()
//使用vite懒加载
let Module = ("@/views/**/*.vue");
("====================================");
(Module);
("====================================");

 
5.将 解析为组件动态
//如果没有子集 证明为路由层
if (!) {
//实现组件懒加载
let paths = loadComponent();
(paths);
}

//懒加载组件
function loadComponent(url: string) {
let path = Module[`/src/views/${url}.vue`];
return path;
}
 
6.调用addRouter实现动态路由添加
//如果没有子集 证明为路由层
if (!) {
//实现组件懒加载
let paths = loadComponent();
 = paths;
(rts);
//添加动态路由
("admin", rts);
}
});
 
  1. 7.检测动态路由添加
  2. //检测动态路由
  3. ((), ("Housepay"));

第四步测试动态路由

配置二级动态

 
<script setup lang="ts"></script>
<template>
admin
<router-link to="/housepay">商铺综合收费</router-link>
<router-link to="/temppay">临时收费</router-link>
<!-- 二级出口 -->
<RouterView></RouterView>
</template>

刷新导致动态路由匹配不到 直接 404

 
刷新 使用动态路径匹配的时候在路由中没有对应的路由 直接匹配到*路由 重定向到404
守卫添加以下代码
//手动添加404相关处理
({
path: "/not-found",
component: NotFound,
});
({
path: "/:pathMatch(.*)*", //vue2 * vue3 改为正则
redirect: "/not-found",
});
(());
//处理
return { path:  };
静态配置中404 *路由删除 采用手动配置。

第五步设置菜单数据缓存

 
//设置菜单数据缓存
("_menu", (Menu));

组件中进行递归
<script setup lang="ts">
interface propType {
children: Array<any>;
}
defineProps<propType>();
</script>
<template>
<template v-for="(item, index) in children">
<template v-if="!">
<el-menu-item index="1-3">{{  }}</el-menu-item>
</template>
<template v-else>
<!-- 当前级是否存在子集 -->
<el-sub-menu index="1-4">
<template #title>{{  }}</template>
//组件递归
<MenuItem :children=""></MenuItem>
</el-sub-menu>
</template>
</template>
</template>

最后实现最终效果