ruoyi vue3 自定义子路由面包屑处理
·
效果图:
a/b/c/新增、编辑、详情之类的 需要展示在面包屑中 因为不需要首页就把首页删除了


代码:
html
<template>
<div class="breadcrumb-box">
当前位置:
<el-breadcrumb class="app-breadcrumb" separator="/">
<!-- <transition-group name="breadcrumb"> -->
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span
:style="{
color: index == levelList.length - 1 ? '#ffffff' : '#b0c6d6',
}"
>{{ item.meta.title }}</span
>
</el-breadcrumb-item>
<!-- </transition-group> -->
</el-breadcrumb>
</div>
</template>
js
<script setup>
import usePermissionStore from "@/store/modules/permission";
import useRouteToPageStore from "@/store/modules/routeToPage";
const route = useRoute();
const permissionStore = usePermissionStore();
const routeToPageStore = useRouteToPageStore();
const levelList = ref([]);
function findParentChain(routes, targetPath, parentPath = "") {
for (const route of routes) {
// 检查当前节点是否匹配目标路径
const currentPath =
parentPath + (route.path.startsWith("/") ? route.path : `/${route.path}`);
if (currentPath.endsWith(`/${targetPath}`) || currentPath === targetPath) {
return [route]; // 返回当前路由对象
}
// 递归检查子节点
if (route.children) {
const childChain = findParentChain(
route.children,
targetPath,
currentPath
);
if (childChain.length > 0) {
// 返回当前路由对象 + 子路由链
return [route, ...childChain];
}
}
}
return [];
}
// 获取完整的面包屑路径
function getBreadcrumb() {
let matched = [];
// 1. 获取当前路由的breadcrumbMenu(如果有)
const breadcrumbMenu = route.meta?.breadcrumbMenu;
const rootMenu = route.meta?.rootMenu;
// 2. 如果有breadcrumbMenu,则从breadcrumbMenu开始构建面包屑
if (breadcrumbMenu) {
const chain = findParentChain(
permissionStore.defaultRoutes.filter((item) => item.path == rootMenu),
breadcrumbMenu
);
matched = chain.filter((item) => item.meta?.title && item.meta);
if (route.meta?.title) {
matched.push({
path: route.path,
meta: { title: routeToPageStore.pageTitle || route.meta.title },
redirect: "noRedirect",
});
}
} else {
// 3. 没有breadcrumbMenu,使用常规方法
const pathNum = findPathNum(route.path);
if (pathNum > 2) {
const reg = /\/\w+/gi;
const pathList = route.path.match(reg).map((item, index) => {
if (index !== 0) item = item.slice(1);
return item;
});
getMatched(pathList, permissionStore.defaultRoutes, matched);
} else {
matched = route.matched.filter((item) => item.meta && item.meta.title);
}
levelList.value = matched.filter((item) => item.meta && item.meta.title);
}
levelList.value = matched;
}
function findPathNum(str, char = "/") {
let index = str.indexOf(char);
let num = 0;
while (index !== -1) {
num++;
index = str.indexOf(char, index + 1);
}
return num;
}
function getMatched(pathList, routeList, matched) {
let data = routeList.find(
(item) =>
item.path == pathList[0] || (item.name += "").toLowerCase() == pathList[0]
);
if (data) {
matched.push(data);
if (data.children && pathList.length) {
pathList.shift();
getMatched(pathList, data.children, matched);
}
}
}
watchEffect(() => {
if (route.path.startsWith("/redirect/")) {
return;
}
getBreadcrumb();
});
getBreadcrumb();
</script>
css
<style lang="scss" scoped>
.breadcrumb-box {
height: 40px;
padding-left: 16px;
display: flex;
align-items: center;
justify-content: flex-start;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 12px;
color: #ffffff;
border-bottom: 1px solid #1c3667;
background-color: #0a0a0a;
.breadcrumb-container {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 12px;
height: 22px;
}
}
.app-breadcrumb {
display: flex;
align-items: center;
height: 22px;
}
.app-breadcrumb.el-breadcrumb {
display: flex;
align-items: center;
font-size: 12px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
:deep(.el-breadcrumb__separator) {
color: #888d98;
}
</style>
router/index.js文件
// 动态路由,基于用户权限动态去加载 在ruoyi原有的这个中加入新的 比如新增页面
export const dynamicRoutes =
{
path: "/system/user/data",
component: Layout,
hidden: true,
permissions: ["system:user:list"],
children: [
{
path: "",
component: () => import("@/views/system/user/components/edit"),
name: "UserEdit",
meta: {
title: "用户管理",
activeMenu: "/system/user", //当前高亮的路由
rootMenu: "/system", // 查找的根路由
breadcrumbMenu: "user", // 面包屑菜单
},
},
],
},
处理动态title 使用 pinia
title: "用户管理",
persist: true, 数据持久化 可以使用pinia的插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
yarn add pinia-plugin-persistedstate
ruoyi自带 store/index.js 引入持久化插件
const store = createPinia();
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
store.use(piniaPluginPersistedstate); // 注入插件
export default store;
因为还有其他逻辑之后我新建一个文件 store/modules/routeToPage.js
const useRouteToPageStore = defineStore("routeToPage", {
state: () => ({
editParams: null, // 存储编辑页参数
pageTitle: null, // 存储页面标题
}),
actions: {
setEditParams(params) {
this.editParams = params;
},
clearEditParams() {
this.editParams = null;
},
setPageTitle(title) {
this.pageTitle = title;
},
clearPageTitle() {
this.pageTitle = null;
},
},
persist: true,
});
export default useRouteToPageStore;
大功告成!!!
更多推荐


所有评论(0)