/**
* 权限管理在后台,前端接收到的是已经过滤完的菜单树
* @menuId 菜单唯一识别
* @menuName 名称
* @icon 图标
* @parentId 父菜单,前端不用,后端用来嵌套树
* @route 只有叶子结点有路由
* @type 是菜单级别,只有一级菜单和二级菜单
* @orderNum 是菜单排序,后台需要用来排序,前端不用
* @children 叶子结点没有该属性或者为空数组
*/
// 获取菜单树
const menuTreeData = [{
"menuId": 1,
"menuName": "系统管理",
"parentId": 0,
"route": null,
"type": 0,
"icon": "el-icon-setting",
"orderNum": 0,
"children": [{
"menuId": 2,
"menuName": "微信用户",
"parentId": 1,
"parentName": "系统管理",
"route": "/miniUser",
"type": 1,
"icon": "el-icon-service",
"orderNum": 1,
"children": []
},
{
"menuId": 3,
"menuName": "菜单管理",
"parentId": 1,
"parentName": "系统管理",
"route": "/menu",
"type": 1,
"icon": "el-icon-news",
"orderNum": 2,
"children": []
}
]
},
{
"menuId": 4,
"menuName": "密码管理",
"parentId": 0,
"route": null,
"type": 0,
"icon": "el-icon-news",
"orderNum": 2,
"children": [
{
"menuId": 5,
"menuName": "个人管理",
"parentId": 4,
"parentName": "密码管理",
"route": null,
"type": 1,
"icon": "el-icon-news",
"orderNum": 1,
"children": [
{
"menuId": 6,
"menuName": "钱包管理",
"parentId": 5,
"parentName": "个人管理",
"route": "/menu",
"type": 2,
"icon": "el-icon-news",
"orderNum": 1,
"children": []
}]
},
{
"menuId": 7,
"menuName": "交易查询",
"parentId": 5,
"parentName": "密码管理",
"route": "/test",
"type": 1,
"icon": "el-icon-news",
"orderNum": 1,
"children": []
}]
}]
这个问题网上有比较多的答案。主要利用Vue组件的name
属性,然后实现递归。
zMenu.vue
组件,其中实现递归逻辑zMenu.vue
<el-menu style="width: 100%;" :collapse="isCollapse" :collapse-transition="false" background-color="#333" text-color="#fff">
<z-menu :menus="menus">z-menu>
el-menu>
<template>
<div>
<template v-for="menu in menus">
<el-submenu v-if="menu.children && menu.children.length >= 1" :index="menu.menuId + ''" :key="menu.menuId">
<template slot="title">
<i :class="menu.icon">i>
<span slot="title">{
{menu.menuName}}span>
template>
<z-menu :menus="menu.children">z-menu>
el-submenu>
<el-menu-item v-else :index="menu.menuId + ''" @click="handleRouter(menu)" :key="menu.menuId">
<i :class="menu.icon">i>
<span slot="title">{
{menu.menuName}}span>
el-menu-item>
template>
div>
template>
<script>
export default {
name: 'zMenu', // 至关重要,就靠这个名字递归了
props: {
menus: {
type: Array,
default: function () {
return [];
},
required: false
}
},
methods: {
handleRouter(menu) {
// 跳转路由
this.$router.push(menu.route);
}
}
}
script>
嵌套中出现了意料之外的,而
标签本身希望里面嵌套的是
,
,
其中之一
- 但是我们又不能直接删掉
,因为
中包含的必须是一个根标签,而v-for
会形成不确定的并列标签
- 于是我们找到了
vue-fragment
这个库
3. 导航栏折叠
- 项目安装
vue-fragment
cnpm install --save vue-fragment
- 在
main.js
中引入
// main.js
import Fragment from 'vue-fragment'
Vue.use(Fragment.Plugin)
- 将
zMenu.vue
中的修改为
即可
<template>
<fragment>
<template v-for="menu in menus">
<el-submenu v-if="menu.children && menu.children.length >= 1" :index="menu.menuId + ''" :key="menu.menuId">
<template slot="title">
<i :class="menu.icon">i>
<span slot="title">{
{menu.menuName}}span>
template>
<z-menu :menus="menu.children">z-menu>
el-submenu>
<el-menu-item v-else :index="menu.menuId + ''" @click="handleRouter(menu)" :key="menu.menuId">
<i :class="menu.icon">i>
<span slot="title">{
{menu.menuName}}span>
el-menu-item>
template>
fragment>
template>
参考链接
递归菜单
导航栏折叠后文字不隐藏
vue-fragment