问题形容
在后盾治理我的项目中,牵涉到权限的货色少数是后端传递过去的数据,前端去展现(当然前端也会做一些管制)。就导航菜单而言,也不能写死了,须要在用户登录了当前,发申请获取用户的对应菜单数据,依据对应的数据去展现对应的菜单。
本文记录一下应用组件递归的形式,封装一个动静的、多级的导航菜单,从而实现动态效果。
看这篇文章之前,能够看看我之前的《vue组件的递归自调用~代码思路剖析》文章,本篇文章是之前文章的延长。地址如下:https://segmentfault.com/a/11...
效果图
咱们先看一下效果图:
思路剖析
首先,咱们要和后端沟通返回的数据格式,咱们晓得前端的el-menu菜单的外围数据属性有四个:
- 菜单的名字name
- 点击菜单进行路由跳转的门路path
- 菜单上小图标icon
- 菜单是不是最内层的菜单,即children是否是空数组,当children为空的时候,就阐明到菜单最里层了。(最里层的菜单children为空数组的时候,点击的时候,做路由跳转)
- 所以须要有name、path、icon、children属性,且得是一个树结构的格局,和左侧导航菜单保持一致。
- 这里咱们模仿一下后端返回的代码
后端返回的el-menu菜单数据
menuArr: [ {// 留神!留神!有children的菜单项,path不会应用的,所以path为什么都无所谓;没children的,即children的length等于0的,才会应用path属性做路由跳转 name: "前端三大框架", path: "前端三大框架", icon: "el-icon-star-off", children: [ { name: "vue页面", path: "/vue", icon: "el-icon-star-off", children: [], }, { name: "react页面", path: "/react", icon: "el-icon-star-off", children: [], }, { name: "angular页面", path: "/angular", icon: "el-icon-star-off", children: [], }, ], }, { name: "后端两大框架", path: "后端两大框架", icon: "el-icon-star-off", children: [ { name: "Spring Boot页面", path: "/springBoot", icon: "el-icon-star-off", children: [], }, { name: "Spring页面", path: "Spring页面", icon: "el-icon-star-off", children: [ { name: "MySql页面", path: "/mysql", icon: "el-icon-star-off", children: [], }, { name: "Redis页面", path: "/redis", icon: "el-icon-star-off", children: [], }, ], }, { name: "Mybatis页面", path: "/mybatis", icon: "el-icon-star-off", children: [], }, ], }, ]
咱们先看一下非动静多级菜单的写法,而后再看一下递归组件动静多级菜单的写法
非动静多级菜单(写死了,不灵便,不倡议应用)
<el-menu :default-active="activeIndex" class="elMenu" background-color="#333" text-color="#B0B0B2" active-text-color="#fff" :unique-opened="true" router ref="elMenu" @select="menuSelect"> <el-submenu index="非叶子节点也须要index属性"> <template slot="title"> <i class="el-icon-star-off"></i> <span>前端三大框架</span> </template> <!-- 这个是没子节点的 没有子内容,用el-menu-item构造 --> <el-menu-item index="/vue"> <i class="el-icon-star-off"></i> <span slot="title">vue页面</span> </el-menu-item> <el-menu-item index="/react"> <i class="el-icon-star-off"></i> <span slot="title">react页面</span> </el-menu-item> <el-menu-item index="/angular"> <i class="el-icon-pear"></i> <span slot="title">angular页面</span> </el-menu-item> </el-submenu> <el-submenu index="非叶子节点也须要index属性哦"> <template slot="title"> <i class="el-icon-star-off"></i> <span>后端两大框架</span> </template> <el-menu-item index="/springBoot"> <i class="el-icon-star-off"></i> <span slot="title">Spring Boot页面</span> </el-menu-item> <!-- 留神看这里有子节点的无子节点的html标签的区别 --> <!-- 这个是有子节点的 还有子内容,用el-submenu构造--> <el-submenu index="非叶子节点也须要index属性哈"> <template slot="title"> <i class="el-icon-star-off"></i> <span>Spring页面</span> </template> <el-menu-item index="/mysql"> <i class="el-icon-star-off"></i> <span slot="title">MySql页面</span> </el-menu-item> <el-menu-item index="/redis"> <i class="el-icon-star-off"></i> <span slot="title">Redis页面</span> </el-menu-item> </el-submenu> <!-- 这个是没子节点的 没有子内容,用el-menu-item构造 --> <el-menu-item index="/mybatis"> <i class="el-icon-star-off"></i> <span slot="title">Mybatis页面</span> </el-menu-item> </el-submenu></el-menu>
发现法则
通过上述代码,咱们发现,el-menu代码大抵分为两类,有子集和没有子集的
- 有子集:
用的是el-submenu标签包template标签指定名字跟很多个el-menu-item标签
- 没子集:
间接用很多个el-menu-item标签
得出上述法则,咱们就能应用递归组件形式去封装一个动静菜单
动静菜单代码
外层菜单局部
html局部
<el-menu :default-active="activeIndex" class="elMenu" background-color="#333" text-color="#B0B0B2" active-text-color="#fff" :unique-opened="true" router ref="elMenu" @select="menuSelect"> <!-- 递归动静菜单 --> <myitem :data="menuArr"></myitem></el-menu>
js局部
import myitem from "./components/myitem.vue"; // 引入递归菜单组件export default { name: "Home", components: { myitem, // 注册一下 }, data() { return { activeIndex: this.$route.path, menuArr: [...] // 数据是上述咱们模仿的数据,#后端返回的el-menu菜单数据# }; }};
内层递归菜单项局部
<template> <div> <template v-for="(item, index) in data"> <!-- 因为有子集和无子集渲染html标签不一样,所以要分为两种状况 状况一:有子集的状况: --> <el-submenu :key="index" :index="item.path" v-if="item.children.length > 0" > <template slot="title"> <i :class="item.icon"></i> <span>{{ item.name }}</span> </template> <myitem :data="item.children"></myitem> </el-submenu> <!-- 状况二:没子集的状况: --> <el-menu-item :key="index" v-else :index="item.path"> <i :class="item.icon"></i> <span slot="title">{{ item.name }}</span> </el-menu-item> </template> </div></template><script>export default { name: "myitem", props: { data: { type: Array, default: [], }, }, // 留神: 在template标签上应用v-for,:key="index"不能写在template标签上,因为其标签不会被渲染,会引起循环谬误};</script>
残缺代码
残缺代码我上传到Gitee下来了,欢送大家下载查看,这样更加不便了解。
地址:https://gitee.com/ah-shuai/dy...