vue 动态显示三级路由

无需 vuex、本地存储实现动态显示三级路由。

目录

一、需求描述: 

二、代码

2.1 路由配置

1. 我的一级菜单和二级菜单的路由配置的:

2. 三级菜单的路由配置:

3. 上面有几个变量和要注意的细节:

2.2 封装导航栏

2.3 封装面包屑

2.4 页面布局


一、需求描述: 

   之前写过一个 element实现动态路由+面包屑,这个需求是嵌套的页面层级太多了,需要在页面中点击某个按钮,跳转到下一个页面(即该页面的子页面),在下一个页面的面包屑中显示所有前一级的路由。面包屑显示关系为:组先 - 父页面 - 当前页面。

   现在这个需求是:已确定路由中包含3级菜单,如果有3级菜单,在点击二级菜单的时候,在面包屑中将该二级菜单下所有的3级菜单都显示出来;如果是一级菜单没有子菜单,或者只有二级菜单,那么面包屑中就显示一级菜单名称或二级菜单名称。如下图:

( 上面图2中,“一级标题3”下应该是“二级标题3-1”,不小心写错了)

二、代码

  由于项目周期比较紧,代码一切从简。

2.1 路由配置

这里分布例举一下我的一级菜单、二级菜单和三级菜单的路由配置,具体 path、name、meta.title、meta.icon、component、redirect 等值需要自己去设置。

1. 我的一级菜单和二级菜单的路由配置的:

{path: '/menu4',name: 'userRoleManage',meta: {title: "一级标题4", leaf: true, hidden: false,icon:"my-icon-labelManage"},component: () => import('@/components/myLayout'),redirect: "/menu4/menu41",children:[{path: 'menu41',name: 'menu41',meta: {title: "一级标题4", hidden: false},component: () => import('@/views/menu4/menu41.vue')}]
},
{path: '/outWh',name: 'outWh',meta: {title: "一级标题3", leaf: false, hidden: false, icon: 'my-icon-packProduct'},component: () => import('@/components/myLayout'),redirect: "/outWh/list",children:[{path: 'list',name: 'list',meta: {title: "二级标题3-1", hidden: false},component: () => import('@/views/outWh/list.vue')},    {path: 'codeInfo',name: 'codeInfo',meta: {title: "二级标题3-2", hidden: false},component: () => import('@/views/outWh/codeInfo.vue')}]
}

2. 三级菜单的路由配置:

{path: '/basicData',name: 'basicData',meta: {title: "一级标题1", leaf: false, hidden: false,icon:"my-icon-labelManage"},component: () => import('@/components/myLayout'), //组件-封装好的头部、导航等页面整体框架redirect: "/basicData/goodsInfo",children:[{path: 'goodsInfo',name: 'goodsInfo',meta: {title: "二级标题1-1", hidden: false},component: () => import('@/views/basicData/goodsInfo.vue')},{path: 'warehouseInfo',name: 'warehouseInfo',meta: {title: "二级标题1-2", hidden: false, threeMenu: true},component: () => import('@/components/myLayout/breadcrumb'), //引入面包屑组件redirect: "/basicData/warehouseInfo/warehouse",children: [{path: 'warehouse',name: 'warehouse',meta: {title: "三级标题1-2-1", hidden: false},component: () => import('@/views/basicData/warehouse.vue')},{path: 'goodsShelf',name: 'goodsShelf',meta: {title: "三级标题1-2-2", hidden: false},component: () => import('@/views/basicData/goodsShelf.vue')},{path: 'goodsPlace',name: 'goodsPlace',meta: {title: "三级标题1-2-4", hidden: false},component: () => import('@/views/basicData/goodsPlace.vue')}]},{path: 'supplier',name: 'supplier',meta: {title: "二级标题1-3", hidden: false},component: () => import('@/views/basicData/supplier.vue')},{path: 'clientInfo',name: 'clientInfo',meta: {title: "二级标题1-4", hidden: false},component: () => import('@/views/basicData/clientInfo.vue')}]
}

3. 上面有几个变量和要注意的细节:

  1. leaf 表示一级菜单下是否有子菜单【在一级菜单的 meta 中书写该变量】。true:只有一级菜单,没有子菜单;false:有子菜单(有二级菜单、三级菜单都是 false);
  2. hidden :该路由配置的信息是否要在导航栏中隐藏起来。true:在导航栏上隐藏起来(即不显示),false:不隐藏(即显示)。
  3. threeMenu:是否有三级菜单【在二级菜单的 meta 中书写该变量】。true:该二级菜单下有 3 级菜单,false:该二级菜单下没有 3 级菜单。
  4. 当有 3 级菜单时,就把该 3 级菜单的二级菜单当做 一级菜单 来设置,在二级菜单中添加 componentredirect 方法。component 指向组件,redirect 重定向到页面。
  5. 有 3 级菜单时,就给该 3 级菜单的二级菜单设置:threeMenu:true,没有的可以不设置。要是想要代码统一,就在所有二级菜单中的 meta 中设置一下。

具体一些的,我在 手把手教你用 element 实现导航栏 这篇文章中有介绍。

2.2 封装导航栏

导航栏的封装我直接拿的 手把手教你用 element 实现导航栏 中的代码。

<template><el-menu id="myAside"router:default-active="$route.matched[1].path"active-text-color="#00BF9F"><!-- 侧导航栏 -->      <template v-for="(item,itemId) in allRouter"><!-- 节点不隐藏 --><template v-if="!item.meta.hidden"><!-- 是否只有一个节点 leaf:true-是只有一个节点 --><template v-if="item.meta.leaf"><el-menu-item :index="item.redirect" :key="itemId" class="oneLeaf"><i :class="item.meta.icon"></i><span slot="title" class="oneLeftTitle">{{item.meta.title}}</span></el-menu-item></template><!-- 多个节点 --><el-submenu v-else :index="item.redirect" :key="itemId"><template slot="title"><i :class="item.meta.icon"></i><span>{{item.meta.title}}</span></template><el-menu-item-group><template v-for="(child,childId) in item.children">       <template>                  <el-menu-item :index="item.path +'/'+ child.path" :key="childId" v-if="!child.meta.hidden">{{child.meta.title}}</el-menu-item>  </template><!-- 判断是否为3级菜单结束--></template></el-menu-item-group></el-submenu></template></template></el-menu>
</template><script>
// import { mapGetters } from "vuex";export default {data(){return {allRouter: this.$router.options.routes}}
}
</script><style scoped lang="scss">
#myAside{border-right:0;.my-icon-labelManage{display: inline-block;width:20px;height:20px;}.my-icon-labelManage{background: url("~@/assets/menu/labelInit.png") center no-repeat;}.my-icon-labelManage:before{content: "\8d3a";font-size: 22px;visibility: hidden;}.el-submenu.is-active, .el-menu-item.is-active{.my-icon-labelManage{background: url("~@/assets/menu/labelInit_active.png") center no-repeat;}    }
}
</style>

不过这里有个细节需要注意一下:

导航栏上激活的选项(即被选中的一级菜单/二级菜单)与 :default-active 属性值有关。当我们点击三级菜单时,导航栏上被激活的是该三级菜单的二级菜单,所以 :default-active 的属性值应该是 二级菜单的 path 值,而不是 当前三级菜单的 $route.path 值。

【这里特地提一下,因为这一步我被卡了一下,三级菜单的面包屑和二级菜单的导航把我绕进去了......想一想怎么描述这个过程,还是有点晕】 

另外,:default-active="$route.matched[1].path" 这个属性值还挺神奇的,要是只有一级和二级菜单也可以用这个属性值代替,以后我写导航的激活就用这个值了嘿嘿~。(有需要的可以自己打印看看)

2.3 封装面包屑

原本我打算根据路由配置中二级菜单的 meta.threeMenu 的属性值,来判断被点击的二级菜单中有没有包含三级菜单,但是因为这是写在二级菜单里面,需要循环一下。后面发现 this.$route.matched 有个很方便的特点:

  1. 路由配置中如果一级路由下没有 children: [],那么 this.$route.matched.length = 1
  2. 路由配置中如果一级路由下有二级菜单,写了一个 children,那么 this.$route.matched.length = 2
  3. 路由配置中如果二级路由下有三级菜单,又写了一个 children,那么 this.$route.matched.length = 3

 总的来说:路由配置中一级菜单下总共包含了几个children,那么 this.$route.matched 的长度 = children数量 + 1。 利用这个特点,就能很方便快速的判断出点击的一级/二级菜单下是否有三级菜单。

 思路:

1. 判断点击的路由是否包含3级菜单。

        由于我配置路由时,没有二级菜单的一级菜单有二级菜单的一级菜单 是根据 leaf 值来判断的,两者都写了 children:[],所以 this.$route.matched.length 都= 2。但是不管是前者还是后者,被点击时,面包屑中显示的都是被点击的那个路由信息(即1级菜单面包屑显示1级菜单名称,2级菜单面包屑显示2级菜单名称)。

2. 如果没有 3级菜单( 即 this.$route.matched.length = 2),就把当前点击的路由信息保存下来。

3. 如果有 3级菜单,那么点击二级菜单时,就要把该二级菜单下的所有 3级菜单的路由信息保存下来。

4. 将保存下来的路由信息在面包屑中显示出来,这里用到 router-link,3级菜单被选中激活时,router-link 会自动生成一个 .router-link-active 的 class 名。

<template><div id="breadcrumb"><!-- 面包屑 --><div class="bg pd20 clear mb20"><router-link v-for="three in threeRouters" :key="three.name" :to="three.path">{{three.meta.title}}</router-link></div><router-view v-if="threeMenuOff"></router-view></div>
</template><script>
export default {data(){return {allRouter: this.$router.options.routes, //获取所有菜单threeRouters: [],threeMenuOff: false}},watch: {"$route": {handler(val,oldval){// console.log("面包屑监听",val, oldval)this.getChildRoute(val)},deep: true,immediate: true}},methods:{getChildRoute(currRoute){console.log("breadcrumb",currRoute,this.allRouter)if(currRoute.matched.length == 2){this.threeRouters = [currRoute]; //直接将当前的路由信息传给组件this.threeMenuOff = false;}else if(currRoute.matched.length == 3){ //说明有3级路由this.allRouter.map(item=>{if(currRoute.matched[0].path == item.path){//二级路由。存所有三级路由的数据item.children.map(child =>{if(currRoute.matched[1].name == child.name){this.threeRouters = JSON.parse(JSON.stringify(child.children));}});}})this.threeMenuOff = true;} //判断结束currRoute.matched.length=3console.log("3ji菜单",this.threeRouters)} ,},
}
</script><style lang="scss" scoped>
#breadcrumb{margin-bottom: 20px;a{float: left;margin-right: 20px;}a.router-link-active{border-bottom:2px solid #f88;}
}
</style>

这里需要注意:三级路由的页面,需要添加 <router-view></roter-view>,否则三级页面显示空白。原因是在配置时,二级路由的 component 指向的是面包屑组件路径而非三级页面所在路径,通过 redirect 重定向到三级页面。

2.4 页面布局

这个部分因为有个需要注意的地方,所以也贴一下代码。

<template><el-container><el-header class="bg" style="height: 80px;"> <v-head></v-head> </el-header><el-container><el-aside width="260px" class="bg"> <my-aside></my-aside> </el-aside><el-main><breadcrumb v-if="!threeMenuOff"></breadcrumb><router-view></router-view></el-main></el-container></el-container>
</template><script>
import vHead from "./vHead"
import myAside from "./myAside"
import breadcrumb from "./breadcrumb"
export default {components: { vHead, myAside, breadcrumb },data(){return {threeMenuOff: false  //3级菜单的不需要面包屑组件,因为在路由中components已经配置了}},watch: {"$route": {handler(val,oldval){console.log("myLayout",val)if(val.matched.length == 3 || val.name == "home"){this.threeMenuOff = true; //不需要面包屑组件,将threeMenuOff = true} else {this.threeMenuOff = false;}},deep: true,immediate: true}},
}
</script>

    这里在原来的布局上添加了 <breadcrumb></bredcrumb> 组件,前面在路由配置中,配置了3级菜单的面包屑,这里添加 breadcrumb 组件是给1级菜单和2级菜单添加面包屑的。同时,通常 首页home 是不需要面包屑的,这里也可以做判断,控制面包屑的显示和隐藏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二章 Vue快速入门-- 18 v-for中key的使用注意事项

注意:如果属性和方法还没定义直接使用的话&#xff0c;就会报 xxx is not defined 导致界面不能正常显示。我看视频教程里老师的可以直接使用&#xff0c;而且界面正常显示&#xff0c;可能是vue版本不同吗&#xff1f;还不清楚 1 <!DOCTYPE html>2 <html lang"…

vue 后端返回二进制流文件,前端如何实现下载?

目录 1. axios 请求二进制流文件导出文件 1.1 后台返回的二进制流&#xff1a; 1.2 使用&#xff1a; 1.3 需要注意以下几点&#xff1a; 2. 关于 arraybuffer 和 blob 2.1 ArrayBuffer 和 blob 2.2 区别 2.3 相互转换 3. 主要参考&#xff1a; 1. axios 请求二进制…

python量化之路:获取历史某一时刻沪深上市公司股票代码及上市时间

python量化之路&#xff1a;获取历史某一时刻沪深上市公司股票代码及上市时间 最近开始玩股票量化&#xff0c;由于想要做完整的股票回测&#xff0c;因此股票的上市和退市信息就必不可少。因为我们回测的时候必须要知道某一日期沪深股票的成分包含哪些对吧。所以我们要把沪深全…

《网页设计创意书》读后感

刚刚收到《网页设计创意书》&#xff0c;确实有点惊喜&#xff0c;开始以为是像之前审读的书一样是一叠叠的打印纸&#xff0c;没想到是一本成品书&#xff0c;拿到手上沉甸甸的&#xff0c;随便翻看了一下&#xff0c;没想到里面竟然还是全彩页印刷的&#xff0c;本书的第一感…

游戏AI –行为树简介

游戏AI是一个非常广泛的主题&#xff0c;尽管有很多资料&#xff0c;但我找不到能以较慢&#xff0c;更容易理解的速度缓慢介绍这些概念的东西。 本文将尝试解释如何基于行为树的概念来设计一个非常简单但可扩展的AI系统。 什么是AI&#xff1f; 人工智能是参与游戏的实体表现…

liteos错误处理(十一)

1. 概述 1.1 基本概念 错误处理指用户代码发生错误时&#xff0c;系统调用错误处理模块的接口函数&#xff0c;完成上报错误信息&#xff0c;并调用用户自己的钩子函数&#xff0c;进行特定的处理。 错误处理模块实现OS内部错误码记录功能。OS内部错误码无法通过接口返回&#…

js 变量提升与函数提升

规则&#xff1a; 函数的提升优先于变量提升。同名的函数会覆盖同名的函数与变量。同名的变量不会覆盖同名的函数。 示例代码1&#xff1a; <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"vi…

mockJs文档(一)

Mock.js 官网 目录 1. 开始安装 1.1 Node&#xff08;CommonJS&#xff09; 1.2 CMD方式 2. 语法规范 2.1 数据模板定义规范 DTD 2.1.1. 属性值是字符串 String 2.1.2. 属性值是数字 Number 2.1.3. 属性值是布尔型 Boolean 2.1.4. 属性值是对象 Object 2.1.5. 属性值…

小程序 获取手机号

【参考小程序开发文档&#xff1a;开发-指南-开放能力-用户信息-获取手机号】 地理位置 wx.getLocation(Object object) | 微信开放文档 手机号 获取手机号 | 微信开放文档 微信信息 小程序与小游戏获取用户信息接口调整&#xff0c;请开发者注意升级。 | 微信开放社区 目录…

CSS布局之脱离文档流详解——浮动、绝对定位脱离文档流的区别

1、代码 &#xff08;1&#xff09;示例代码1 <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><meta http-e…

小程序 获取当前城市位置-高德地图

微信小程序 wx.getLocation 只能获取到经纬度&#xff0c;想要获取具体城市信息&#xff0c;需要使用地图插件。公司要求使用 高德地图&#xff0c;在使用上&#xff0c;几个地图的代码步骤都差不多。 目录 1. 查看官方文档 1.1 申请高德地图Key&#xff0c;点击查看申请key…

网页端调用企业微信扫一扫 详细过程

效果展示&#xff08;需要使用微信内置浏览器打开&#xff09;&#xff1a; 目录 1. 快速集成H5开发应用 1.1 开始 1.2 创建应用 1.2.1 登录管理后台 1.2.2 添加自建应用 1.2.3 配置应用 1.2.4 获取应用的 AgentID 与 Secret 1.3 配置应用 1.3.1 配置应用主页 1.3.2 配置…

获取ip地址

代码 ///<summary>///取得客户端真实IP。如果有代理则取第一个非内网地址 ///</summary>publicstringIPAddress { get{ stringresult String.Empty; result HttpContext.Current.Request.ServerVariables["HTTP_X_FORWAR…

微信小程序 监听位置信息

wx.onLocationChange(function callback) | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/api/location/wx.onLocationChange.html 小程序 获取当前城市位置-高德地图_Start2019-CSDN博客小程序获取位置信息&#xff0c;包括省市区、用户…

通过构建Cocoapods私有库进行组件化开发探索

专题一 一、创建私有索引库 选Github或者码云都可以&#xff0c;本例以Github为例。创建私有索引库用来作为自己组件库的索引&#xff1a; 二、本地添加私有索引库 添加&#xff1a;pod repo add 索引库名称 索引库地址 例&#xff1a;pod repo add ZYHModule https://github.c…

layui 父页面弹框中获取子页面的内容

layer弹层组件开发文档 - Layuihttps://www.layui.site/doc/modules/layer.html#layer.getChildFrame 需求及代码分析 如上图&#xff0c;原来是点击一个按钮跳转到子页面&#xff0c;现在想改为&#xff1a;点击按钮&#xff0c;在当前页打开。因为不想要重写子页面的样式及内…

在JBoss Fuse / Fabric8 / Karaf中使用Byteman

您是否曾经尝试过了解一些非常简单的方法不起作用的过程&#xff1f; 您正在任何众所周知的上下文中编写代码&#xff0c;无论出于何种原因它都无法正常工作。 而且您信任您的平台&#xff0c;因此您认真阅读了所有日志。 而且&#xff0c;您仍然不知道为什么某些行为不符合预…

个人作业——Alpha项目测试

一、 这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/ 这个作业要求在哪里 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/3338 团队名称 西柚皇家编程团队&#xff1a;https://www.cnblogs.com/TakeRa…

Windows7下Docker的安装

转自 https://blog.csdn.net/xiangxiezhuren/article/details/79698913 无法打开图3&#xff0c;打开属性。给其添加git路径 无法使用图2下载 https://www.cnblogs.com/huang-yc/p/10350408.html 转载于:https://www.cnblogs.com/shufeiyang/p/11016177.html

简而言之,JUnit:单元测试断言

简而言之&#xff0c;本章涵盖了各种单元测试断言技术。 它详细说明了内置机制&#xff0c; Hamcrest匹配器和AssertJ断言的优缺点 。 正在进行的示例扩大了该主题&#xff0c;并说明了如何创建和使用自定义匹配器/断言。 单元测试断言 信任但要验证 罗纳德里根&#xff08;R…