Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Vue+abp增加三级菜单

Vue+abp增加三级菜单

作者头像
用户6362579
发布于 2019-12-30 09:37:28
发布于 2019-12-30 09:37:28
1.3K00
代码可运行
举报
文章被收录于专栏:小神仙小神仙
运行总次数:0
代码可运行

title: "Vue+abp增加三级菜单" publishDate: 2019-12-26 17:28:38 +0800 date: 2019-12-26 17:28:38 +0800 categories: Vue+abp增加三级菜单 position: problem ---

原生vue版的abp只支持2级菜单,项目需要增加成3级菜单,一番搜索。成果如下


增加3级菜单显示

修改components->shrinkable-menu->components->sidebarMenu文件,增加一级菜单,并增加两个方法hasChildren和getChildren,避免html因为没有children属性报错

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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">
    hasChildren(item:any){
        return !!item.children&&item.children.length>0
    }
    getChildren(item:any){
        return item.children;
    }
</script>

修改显示路由方法

就是显示图上这个

这个方法在lib->util.ts文件中,我是抄的Vue iview-admin模板二级菜单改为三级菜单,根据abp做了一些调整,修改setCurrentPath方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  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: currentPathObj.meta.title},
                path: "",
                name: ""
              },
              {
                meta: {title: childObj.meta.title},
                path: "", //设为空是因为此二级菜单没有实际页面且用于面包屑组件显示,path为空的将不可单击
                name: ""
              },
              {
                meta: {title: thirdObj.meta.title},
                path:
                  currentPathObj.path +
                  "/" +
                  childObj.path +
                  "/" +
                  thirdObj.path,
                name: thirdObj.name
              }
            ];
          }
        }
      }
    }
    vm.$store.commit("app/setCurrentPath", currentPathArr);
    return currentPathArr;
  }

修改根据菜单权限加载菜单

如果不修改加载权限,则第三级菜单无法用权限控制,第二级菜单也必须定义权限才能显示。如果第二级菜单只是目录,第三级菜单都没有权限,那么第二级目录是不应该显示出来的。 在store->modules->app.ts中修改updateMenulist方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
updateMenulist(state: AppState) {
    let menuList: Array<Router> = [];
    [...appRouters,...organizeRouters,...labRouters,...labcheckRouters,
        ...devRouters,...labreportRouters,...appraiseRouters].forEach((item, index) => {
        if (item.permission !== undefined) {
            Util.addHasPermissionChileMenu(item);
            if(item.children&&item.children.length>0){
                menuList.push(item);
            }
            // let hasPermissionMenuArr: Array<Router> = [];
            // hasPermissionMenuArr = item.children.filter(child => {
            //     if (child.permission !== undefined) {
            //         if (Util.abp.auth.hasPermission(child.permission)) {
            //             return child;
            //         }
            //     } else {
            //         return child;
            //     }
            // });
            // if (hasPermissionMenuArr.length > 0) {
            //     item.children = hasPermissionMenuArr;
            //     menuList.push(item);
            // }
        } else {
            if (item.children.length === 1) {
                menuList.push(item);
            } else {
                let len = menuList.push(item);
                let childrenArr = [];
                childrenArr = item.children.filter(child => {
                    return child;
                });
                let handledItem = JSON.parse(JSON.stringify(menuList[len - 1]));
                handledItem.children = childrenArr;
                menuList.splice(len - 1, 1, handledItem);
            }
        }
    });
    state.menuList = menuList;
}

在lib->util文件中,增加方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
addHasPermissionChileMenu(item:any){
    let that=this;
    let hasPermissionMenuArr: Array<Router> = [];
    if(!item.children){
        return;
    }
    hasPermissionMenuArr = item.children.filter(child => {  
        let isFather=!!child.children;
        that.addHasPermissionChileMenu(child);
        let hasChildren=!!child.children
        if (isFather&&!hasChildren) {
            return false;
        }

        if (child.permission !== undefined) {
            if (that.abp.auth.hasPermission(child.permission)) {
                return child;
            }
        } else {
            return child;
        }
    });
    if (hasPermissionMenuArr.length > 0) {
        item.children = hasPermissionMenuArr;
    }else{
        item.children=null;
    }
}

增加三级菜单路由

在component目录中增加一个显示三级菜单内容的容器three-leve-container.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
<div>
  <router-view></router-view>
</div>

</template>

<script lang="ts">
import { Component, Vue, Inject } from "vue-property-decorator";
import ViewUI from "view-design";
import AbpBase from "../lib/abpbase";
import util from "../lib/util";
@Component({
  components: {}
})
export default class ThreeLeveContainer extends AbpBase {
      
}
</script>

<style>
</style>

现在可以修改你的菜单定义,在二级菜单下像第一级菜单下增加二级菜单一样增加三级菜单了,二级菜单的权限可以是undefined,二级菜单的component要定义成刚才增加的路由组件,这样不需要在后端定义具体的权限,自动根据三级菜单的权限决定是否显示二级菜单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  {
    path: "/menu1",
    name: "menu1",
    permission: "",
    meta: { title: "menu1" },
    icon: "&#xe68a;",
    component: main,
    children: [
      {
        path: "menu2",
        permission: undefined,
        meta: { title: "menu2" },
        name: "menu2",
        component:() => import("../components/three-leve-container.vue"),
        children: [
        {
            path: "menu3",
            permission: "menu3",
            meta: { title: "menu3" },
            name: "menu3",
            component: () =>
            import("../views/xxxx.vue")
        }
        ]
      }]
  }

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Vue3使用递归组件封装El-Menu多级菜单
明知山
2023/09/06
1K0
Vue3使用递归组件封装El-Menu多级菜单
电商后台管理系统主页布局[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143016.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/31
1.3K0
电商后台管理系统主页布局[通俗易懂]
Spring Boot+Vue3 动态菜单实现思路梳理
「松哥最近正在录制 TienChin 项目视频~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦。」 ---- 关于 Spring Boot + Vue3 的动态菜单,松哥之前已经写了两篇文章了,这两篇文章主要是从代码上和大家分析动态菜单最终的实现方式,但是还是有小伙伴觉得没太看明白,感觉缺乏一个提纲挈领的思路,所以,今天松哥再整一篇文章和大家再来捋一捋这个问题,希望这篇文章能让
江南一点雨
2022/07/18
1.2K0
Spring Boot+Vue3 动态菜单实现思路梳理
Vue 动态添加路由及生成菜单
写后台管理系统,估计有不少人遇过这样的需求:根据后台数据动态添加路由和菜单。 为什么这么做呢?因为不同的用户有不同的权限,能访问的页面是不一样的。 在网上找了好多资料,终于想到了解决办法。
谭光志
2020/09/28
3.7K0
【vite+vue3+Ts+element-plus】肩并肩带你写后台管理之主页面开发(侧边栏菜单生成、标签栏开发)
页面比较简单,主要分为左侧的菜单栏,顶部的导航栏(折叠左侧菜单,切换暗黑模式,员工账号名,退出登录),再下面的标签栏,之后就是主页面显示区域。
十里青山
2023/04/28
4.5K0
【vite+vue3+Ts+element-plus】肩并肩带你写后台管理之主页面开发(侧边栏菜单生成、标签栏开发)
layui三级菜单渲染
项目做完了,可以有时间写写博客了。 今天给大家讲解一下layui的三级动态加载菜单含后端代码。 我是最近刚学的layui,非常感谢贤心大神。开发出这么牛逼ui的框架。 声明:KingYiFan前段
猿码优创
2019/07/27
2.5K1
VUE项目后台管理系统(四)左边菜单动态展示,不仅可以折叠,而且点击不同的菜单,右边展示不同的页面
首先后端的接口要返回菜单的list集合,是json格式,我使用的是python接口
一写代码就开心
2021/06/17
1.4K0
VUE项目后台管理系统(四)左边菜单动态展示,不仅可以折叠,而且点击不同的菜单,右边展示不同的页面
Vue电商实践项目(二)
1.实现后台首页的基本布局 2.实现左侧菜单栏 3.实现用户列表展示 4.实现添加用户
用户6808043
2022/02/24
5.1K0
用Spring Boot+Vue做微人事项目第七天
用Spring Boot+Vue做微人事项目第七天
Java架构师必看
2021/05/14
5970
用Spring Boot+Vue做微人事项目第七天
Vue 里,多级菜单要如何设计才显得专业?
松哥最近正在录制 TienChin 项目视频~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦。 ---- 老生常谈了! 虽然我们是 Java 猿,但是写起来前端代码也不含糊!今天我想来和大家聊聊这个前端的动态菜单,要如何设计才显得专业!还是以我们的 TienChin 项目为例,大家一起来看看。 先来一张截图看看效果: 那么这样的菜单是如何设计出来的呢? 今天我也不想和大家聊过
江南一点雨
2022/06/29
1.1K0
Vue 里,多级菜单要如何设计才显得专业?
基于Vue的电商后台管理系统(2)
上期已经实现该系统的登陆界面、路由、登录、退出及导航守卫功能,本期将继续完善该系统的以下功能:从后端获取后台列表数据并渲染到前端页面、用户列表的展示、修改、删除和添加。
全栈程序员站长
2022/06/30
1.1K0
基于Vue的电商后台管理系统(2)
vue 项目中自定义布局与左侧菜单及路由跳转功能的实现(简易版)
在 Vue项目中,实现自定义布局与左侧菜单及路由跳转功能,对于笔者这种不是精通前端开发的同学一向是比较困难的。以前都是在开源项目的基础上扩展自己的功能,比较著名的开源项目 vue-element-admin 就是开源项目的作者通过定义实现的左侧菜单和路由跳转的。不过 vue-element-admin 项目使用的 vue 版本还停留在 vue2,现在市场上新项目普遍都用 vue3 技术了, 但是 vue-element-admin 项目也相应地出了 Vue3 版本,对应的 gitee 仓库地址为:https://gitee.com/youlaiorg/vue3-element-admin.git
用户3587585
2024/05/10
1.8K0
vue 项目中自定义布局与左侧菜单及路由跳转功能的实现(简易版)
抛弃node和vscode,如何用记事本开发出一个完整的vue前端项目
写这篇文章的初衷并不是要大家真的不用node和vscode,说实话前端发展成今天这样,在实际开发中确实离不开node和vscode这类工具了,但往往工具用多了我们自己也成了一个工具人!
人人都是码农
2025/01/20
1410
抛弃node和vscode,如何用记事本开发出一个完整的vue前端项目
React 折腾记 - (3) 结合Mobx实现一个比较靠谱的动态tab水平菜单,同时关联侧边栏
前言 动态tab水平菜单,这个需求很常见,特别是对于后台管理系统来说; 因为当我们侧边栏层级多了,你要找到一个子菜单,必须找,展开,点击. 而有了这个,我们就能节省不少时间,体验上来说也会改善不少 实
CRPER
2018/08/28
3.2K0
React 折腾记 - (3) 结合Mobx实现一个比较靠谱的动态tab水平菜单,同时关联侧边栏
【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs
这个是不是有点繁琐?尤其是路由的设置和菜单的配置,是不是很雷同?那么能不能简单一点呢?如果可以实现设置一次就全部搞定的话,那么是不会很香呢?
用户1174620
2022/05/26
6.1K0
【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs
前端成神之路-vue前端项目02
1.实现后台首页的基本布局 2.实现左侧菜单栏 3.实现用户列表展示 4.实现添加用户
海仔
2021/03/20
4K0
vue3 + elemenplus实现导航栏
今天实现一下导航栏。文章开始前先新建几个文件夹,用于一会儿存放我们的代码。(使用vite创建)。
用户4793865
2023/01/12
9.4K1
vue3 + elemenplus实现导航栏
Vue 递归多级菜单
Menu 组件外层是一个 ul 标签,内部是 vFor 遍历生成的 MenuItem
JS菌
2019/05/14
3.8K1
Vue2动态路由
    一般管理端的菜单栏是根据登录用户角色不同,动态生成的,在vue中我们不止菜单栏需要动态生成,同时我们路由也需要动态生成。
用户5899361
2023/03/25
1.1K0
Vue2动态路由
【wiki知识库】05.分类管理实现--前端Vue模块
除了分类管理,我们的首页也变动了一下。首页的导航栏加载的是我们已经有的分类,同时还加上了一个欢迎页面。
哈__
2024/06/06
1190
【wiki知识库】05.分类管理实现--前端Vue模块
推荐阅读
相关推荐
Vue3使用递归组件封装El-Menu多级菜单
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验