Loading [MathJax]/jax/output/CommonHTML/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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
RESTful API 设计最佳实践
Web API 近几年变得越来越火,而简洁的 API 设计在多后端系统交互应用中也变得尤为重要。通常,会使用 RESTful API 来作为我们的 Web API 。本文介绍了几种简洁 RESTful API 设计的最佳实践。
用户7657330
2020/08/14
6560
RESTful API的十个最佳实践1. 使用名词而不是动词 2. Get方法和查询参数不应该改变资源状态3. 使用名词的复数形式 4. 为关系使用子资源 5. 使用HTTP头决定序列化格式 6. 使
WebAPI在过去几年里非常的盛行,我们很多以往的技术手段都慢慢的转换为使用WebAPI来开发,因为它的语法简单规范化,以及轻量级等特点,这种方式收到了广泛的推崇。 通常我们使用RESTFul(Representational State Transfer)的设计方式来设计Web api,这通常用来分离API结构了业务逻辑,它使用典型的HTTP方法,诸如GET,POST.DELETE,PUT来和资源进行交互。 以下是设计RESTful API的是个最佳实践: 1. 使用名词而不是动词 为了易于理解,为资源使
小白哥哥
2018/03/07
2.9K0
Restful 架构 API 接口经典设计误区
目前微服务架构盛行,在了解了很多的实际微服务项目中,发现很多同事在设计业务 API 接口时,写法五花八门,现总结下目前项目上设计业务 API 接口的一些比较经典误区写法。
猿芯
2021/05/27
8240
分布式系统核心:REST风格的架构,REST成熟度模型及REST API管理
正确、完整地使用REST是困难的,关键在于RoyFielding所定义的REST只是一种架构风格,它并不是规范,所以也就缺乏可以直接参考的依据。好在Leonard Richardson补充了这方面的不足。
IT大咖说
2021/06/15
9160
分布式系统核心:REST风格的架构,REST成熟度模型及REST API管理
RESTful API 设计最佳实践
原文出处:RESTful API Design. Best Practices in a Nutshell. 原文:RESTful API Design. Best Practices in a Nutshell. 作者:Philipp Hauer 项目资源的URL应该如何设计?用名词复数还是用名词单数?一个资源需要多少个URL?用哪种HTTP方法来创建一个新的资源?可选参数应该放在哪里?哪些不涉及资源操作的URL呢?实现分页和版本控制的最好方法是什么?因为有太多的疑问,设计RES
崔庆才
2018/04/08
1.4K0
RESTful API 设计最佳实践
RESTful API 最佳实践
在参考了GitHub API设计和大量博客文章后总结了一下RESTful API的设计,分享如下。想要更好的理解RESTful API首先需要理解如下概念:
哲洛不闹
2018/09/14
1.9K0
RESTful API 最佳实践
RESTful API 设计最佳实践
背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API是否应该加入版本信息?当你开始写一个app的时候,特别是后端模型部分已经写完的时候,你不得不殚精竭虑的设计和实现自己app的public API部分。因为一旦发布,对外发布的API将会很难改变。 在给SupportedFu设计API的时候,我试图以实用的角度来解决上面提到的问题。我希望可以设计出容易使用,容
张善友
2018/01/29
1.7K0
RESTful API 设计最佳实践
RESTful API 设计指南
网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备......)。 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致API构架的流行,甚至出现"API First"的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。我以前写过一篇《理解RESTful架构》,探讨如何理解这个概念。 今天,我将介绍RESTful API的设计细节,探讨如何设计一套合理、好用的API。我的主要参考了两篇文章(1,2)
ruanyf
2018/04/13
1.1K0
RESTful API 设计指南
RESTful API 设计指南
网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备......)。
OwenZhang
2021/12/08
6710
RESTful API 设计指南
RESTful API 规范 v1.0
本文介绍了RESTful API规范及其在开发中的应用,强调了其设计原则、通信协议、状态码、HATEOAS等方面的重要性。同时,通过举例说明,让读者更好地理解和掌握这些概念和技术。
IMWeb前端团队
2018/01/08
1.2K0
【RESTful】RESTful API 接口设计规范 | 示例
参考官方文档:https://tools.ietf.org/html/rfc2616
前端修罗场
2023/10/07
1.8K0
【RESTful】RESTful API 接口设计规范 | 示例
13个构建RESTful API的最佳实践
原文链接:https://www.sitepoint.com/build-restful-apis-best-practices/[1]
chuckQu
2022/11/28
1.3K0
浅谈 RESTful API
全称:REST,全称是Resource Representational State Transfer,即:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。
Spark学习技巧
2021/02/12
1K0
浅谈 RESTful API
设计 API 的 22 条最佳实践,实用!
今天,我们将讨论一些可遵循的最佳实践。我们将保持简短和甜蜜——所以系好安全带,出发咯!
程序员小富
2022/04/06
1.3K0
设计 API 的 22 条最佳实践,实用!
Restful API 接口规范详解
RESTful API 是应用程序接口 (API) 的一种架构风格,它使用 HTTP 请求来访问和使用数据。该数据可用于 GET、PUT、POST 和 DELETE 数据类型,这些数据类型是指有关资源的操作的读取、更新、创建和删除。
刺槐儿
2023/11/19
12.5K2
深入理解什么是RESTful API ?
越来越多的人开始意识到,网站即软件,而且是一种新型的软件。   这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点。   网站开发,完全可以采用软件开发的模式。但是传统上,软件和网络是两个不同的领域,很少有交集;软件开发主要针对单机环境,网络则主要研究系统之间的通信。互联网的兴起,使得这两个领域开始融合,** 现在我们必须考虑,如何开发在互联网环境中使用的软件。**
AWeiLoveAndroid
2018/09/03
3.2K0
深入理解什么是RESTful API ?
重学SpringBoot系列之RestFul接口及常用注解
API(Application Programming Interface),顾名思义:是一组编程接口规范,客户端与服务端通过请求响应进行数据通信。REST(Representational State Transfer)表述性状态传递,决定了接口的形式与规则。RESTful是基于http方法的API设计风格,而不是一种新的技术.
大忽悠爱学习
2021/12/07
1.7K0
重学SpringBoot系列之RestFul接口及常用注解
RESTful 最佳实践
RESTful 是目前最流行的 API 规范,适用于 Web 接口规范的设计。让接口易读,且含义清晰。本文将介绍如何设计易于理解和使用的 API,并且借助 Docker api 的实践说明。
码哥字节
2020/03/24
1K0
深入理解什么是RESTful API ?
越来越多的人开始意识到,网站即软件,而且是一种新型的软件。   这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点。   网站开发,完全可以采用软件开发的模式。但是传统上,软件和网络是两个不同的领域,很少有交集;软件开发主要针对单机环境,网络则主要研究系统之间的通信。互联网的兴起,使得这两个领域开始融合,** 现在我们必须考虑,如何开发在互联网环境中使用的软件。**
竹清
2018/08/31
6430
深入理解什么是RESTful API ?
RESTful规范Api最佳设计实践
RESTful是目前比较流行的接口路径设计规范,基于HTTP,一般使用JSON方式定义,通过不同HttpMethod来定义对应接口的资源动作,如:新增(POST)、删除(DELETE)、更新(PUT、PATCH)、查询(GET)等。
恒宇少年
2019/10/10
9620
相关推荐
RESTful API 设计最佳实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验