ABP 模板二级菜单改三级菜单

443 阅读1分钟

ABP 模板二级菜单改三级菜单

  1. 修改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>
  1. 修改路由 改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;
  }

可能会报错的问题

  1. 提示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: "&#xe611;",
    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"),
          },
        ],
      },
  }
  1. 提示# 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>

有小伙伴还有其他问题,欢迎留言讨论,觉得对你有帮助的小伙伴,动动小手点一个免费的赞!