ABP 模板二级菜单改三级菜单
- 修改sidebarMenu文件,增加三级菜单
<style lang="less">
@import "../styles/menu.less";
</style>
<template>
<Menu
ref="sideMenu"
:active-name="$route.name"
:open-names="openNames"
:theme="menuTheme"
width="auto"
@on-select="changeMenu"
>
<template v-for="item in menuList">
<MenuItem
v-if="item.children.length <= 0"
:name="item.children[0].name"
:key="item.name"
>
<!-- <Icon :type="item.icon" :size="iconSize"></Icon> -->
<span class="iconfont">{{ item.icon }}</span>
<span>{{ itemTitle(item) }}</span>
</MenuItem>
<Submenu
v-if="item.children.length > 0 && !item.meta.hidden"
:name="item.name"
:key="item.name"
>
<template slot="title">
<i class="iconfont" v-html="item.icon"></i>
<span>{{ itemTitle(item) }}</span>
</template>
<template v-for="child in item.children">
<MenuItem
v-if="!hasChildren(child) && !child.meta.hidden"
:name="child.name"
:key="child.name"
>
<i class="iconfont" v-html="child.icon"></i>
<span> {{ L(child.meta.title) }}</span>
</MenuItem>
<Submenu
v-if="hasChildren(child) && !child.meta.hidden"
:name="child.name"
:key="child.name"
>
<template slot="title">
<i class="iconfont" v-html="child.icon"></i>
<span>{{ itemTitle(child) }}</span>
</template>
<template v-for="ss in child.children">
<MenuItem
v-if="!hasChildren(ss) && !ss.meta.hidden"
:name="ss.name"
:key="ss.name"
>
<i class="iconfont" v-html="ss.icon"></i>
<span> {{ L(ss.meta.title) }}</span>
</MenuItem>
</template>
</Submenu>
</template>
</Submenu>
</template>
</Menu>
</template>
<script lang="ts">
import { Component, Vue, Inject, Prop, Emit } from "vue-property-decorator";
import AbpBase from "../../../lib/abpbase";
@Component({})
export default class SidebarMenu extends AbpBase {
name: string = "sidebarMenu";
@Prop({ type: Array }) menuList: Array<any>;
@Prop({ type: Number }) iconSize: number;
@Prop({ type: String, default: "dark" }) menuTheme: string;
@Prop({ type: Array }) openNames: Array<string>;
itemTitle(item: any): string {
return this.L(item.meta.title);
}
@Emit("on-change")
changeMenu(active: string) {}
updated() {
this.$nextTick(() => {
if (this.$refs.sideMenu) {
(this.$refs.sideMenu as any).updateActiveName();
}
});
}
hasChildren(item: any) {
return !!item.children && item.children.length > 0;
}
getChildren(item: any) {
return item.children;
}
}
</script>
- 修改路由 改
util.ts文件
setCurrentPath(vm: Vue, name?: string) {
let title = "";
let isOtherRouter = false;
vm.$store.state.app.routers.forEach((item) => {
if (item.children.length === 1) {
if (item.children[0].name === name) {
title = util.handleTitle(vm, item);
if (item.name === "otherRouter") {
isOtherRouter = true;
}
}
} else {
item.children.forEach((child) => {
if (child.name === name) {
title = util.handleTitle(vm, child);
if (item.name === "otherRouter") {
isOtherRouter = true;
}
}
});
}
});
let currentPathArr = [];
//去首页
if (name === "home_index") {
currentPathArr = [
{
meta: {
title: util.handleTitle(
vm,
util.getRouterObjByName(vm.$store.state.app.routers, "home_index")
),
},
path: "",
name: "home_index",
},
];
}
//去导航菜单一级页面或者OtherRouter路由中的页面
else if (
(name.indexOf("_index") >= 0 || isOtherRouter) &&
name !== "home_index"
) {
currentPathArr = [
{
meta: {
title: util.handleTitle(
vm,
util.getRouterObjByName(vm.$store.state.app.routers, "home_index")
),
},
path: "/home",
name: "home_index",
},
{
meta: { title: title },
path: "",
name: name,
},
];
}
//去导航菜单二级页面或三级页面
else {
let currentPathObj = vm.$store.state.app.routers.filter((item) => {
var hasMenu;
if (item.children.length <= 1) {
hasMenu = item.children[0].name === name;
return hasMenu;
} else {
let i = 0;
let childArr = item.children;
let len = childArr.length;
while (i < len) {
//如果是三级页面按钮,则在二级按钮数组中找不到这个按钮名称
//需要二级页面下可能出现三级子菜单的情况逻辑加入
if (childArr[i].name === name) {
hasMenu = true;
return hasMenu;
}
i++;
}
//如果一级,二级菜单下都没有此按钮名称,则遍历三级菜单
if (!hasMenu) {
for (let m = 0; m < childArr.length; m++) {
if (!childArr[m].children) continue;
let sonArr = childArr[m].children;
for (let n = 0; n < sonArr.length; n++) {
if (sonArr[n].name === name) {
hasMenu = true;
return hasMenu;
}
}
}
}
return false;
}
})[0];
if (
currentPathObj.children.length <= 1 &&
currentPathObj.name === "home"
) {
currentPathArr = [
{
meta: { title: "HomePage" },
path: "main/home",
name: "home",
},
];
} else if (
currentPathObj.children.length <= 1 &&
currentPathObj.name !== "home"
) {
currentPathArr = [
{
meta: { title: "HomePage" },
path: "main/home",
name: "home",
},
{
meta: { title: currentPathObj.meta.title },
path: "",
name: name,
},
];
} else {
//如果是三级页面按钮,则在二级按钮数组中找不到这个按钮名称
//需要二级页面下可能出现三级子菜单的情况逻辑加入
let childObj = currentPathObj.children.filter((child) => {
return child.name === name;
})[0];
//二级页面
if (childObj) {
currentPathArr = [
{
meta: { title: "HomePage" },
path: "main/home",
name: "home",
},
{
meta: { title: currentPathObj.meta.title },
path: "",
name: "",
},
{
meta: { title: childObj.meta.title },
path: currentPathObj.path + "/" + childObj.path,
name: name,
},
];
}
//childobj为undefined,再从三级页面中遍历
else {
let thirdObj;
let childObj = currentPathObj.children.filter((child) => {
let hasChildren;
hasChildren = child.name === name;
if (hasChildren) return hasChildren;
if (child.children) {
let sonArr = child.children;
for (let n = 0; n < sonArr.length; n++) {
if (sonArr[n].name === name) {
thirdObj = sonArr[n];
hasChildren = true;
return hasChildren;
}
}
}
return hasChildren;
})[0];
if (thirdObj && childObj) {
currentPathArr = [
{
meta: { title: "HomePage" },
path: "main/home",
name: "home",
},
{
meta: { title: thirdObj.meta.title },
path:
currentPathObj.path +
"/" +
childObj.path +
"/" +
thirdObj.path,
name: thirdObj.name,
},
];
}
}
}
}
vm.$store.commit("app/setCurrentPath", currentPathArr);
return currentPathArr;
}
可能会报错的问题
- 提示
Error in callback for watcher "$route": "TypeError: Cannot read property 'children' of undefined"
- 此问题实测是因为
router.ts文件具体如下
export const appRouters: Array<Router> = [
{
path: "/setting",
name: "setting",
permission: "",
meta: {
title: "SystemSettings",
},
icon: "",
component: main,
children: [
//当只有一个三级路由菜单时就会报错 解决办法添加一个二级菜单组件
{
path: "test",
permission: "Pages.Tenants",
meta: {
title: "Test",
},
name: "test",
component: () => import("../views/setting/test/test.vue"),
children: [
{
path: "test1",
permission: "Pages.Tenants",
meta: {
title: "Test1",
},
name: "test1",
component: () => import("../views/setting/test/test1.vue"),
},
{
path: "test2",
permission: "Pages.Tenants",
meta: {
title: "Test2",
},
name: "test2",
component: () => import("../views/setting/test/test2.vue"),
},
],
},
}
- 提示
# Duplicate keys detected: 'home'. This may cause an update error.-breadcrumb-nav.vue文件的v-for的key重复了
<template>
<Breadcrumb>
<BreadcrumbItem
v-for="(item, index) in currentPath"
:to="item"
:key="item.name + index"
>{{ itemTitle(item) }}</BreadcrumbItem
>
</Breadcrumb>
</template>
有小伙伴还有其他问题,欢迎留言讨论,觉得对你有帮助的小伙伴,动动小手点一个免费的赞!