递归组件实现Element树形Menu菜单

分享一波动态生成侧边栏 并且着重分享一个大坑!

1:模拟菜单数据(开发情况下获取后台数据)

const menuList = [
    {
        title: '首页',
        key: '/home',
        icon: 'el-icon-s-home'
    },
    {
        title: '表单',
        key: '/form',
        icon: 'el-icon-film',
        children: [
            {
                title: '登录',
                key: '/form/login',
                icon:'el-icon-s-custom',
                children:[
                    {
                        title:'普通登录',
                        icon:'el-icon-pie-chart'
                    },
                    {
                        title:'高级登录',
                        icon:'el-icon-collection-tag'
                    }
                ]
            },
            {
                title: '注册',
                key: '/form/reg',
                icon:'el-icon-s-opportunity'
            }
        ]
    },
    {
        title: '表格',
        key: '/table',
        icon: 'el-icon-receiving',
        children: [
            {
                title: '基础表格',
                key: '/table/basic',
                icon:'el-icon-date'
            },
            {
                title: '高级表格',
                key: '/table/high',
                icon:'el-icon-document-copy'
            }
        ]
    },
    {
        title: '富文本',
        key: '/rich',
        icon:'el-icon-wallet'
    },
    {
        title: '城市管理',
        key: '/city',
        icon: 'el-icon-office-building'
    },
    {
        title: '订单管理',
        key: '/order',
        icon: 'el-icon-notebook-1',
        children: [
            {
                title: '订单详情',
                key: 'detail',
                icon:'el-icon-reading'
            },
            {
                title: '结束订单',
                key: 'finish',
                icon:'el-icon-data-line'
            }
        ]
    },
    {
        title: '车辆地图',
        key: '/bikeMap',
        icon:'el-icon-place'
    },
    {
        title: '权限设置',
        key: '/permission',
        icon:'el-icon-key'
    },
];
export default menuList;

2:页面主体文件(Main.vue)

<template>
  <div class="main">
      <el-container>
        <el-aside style="width:auto;">
            <div class="logo" v-if="!isCollapse">
              <h1>Admin</h1>
            </div>
            <div class="logo" v-else>
              <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
            </div>
            <menu-list :list="List" :isCollapse="isCollapse"></menu-list>
        </el-aside>
        <el-container>
          <el-header>
              <i class="el-icon-menu" @click="isCollapse = !isCollapse"></i>
          </el-header>
          <el-main>Main</el-main>
          <el-footer>Footer</el-footer>
        </el-container>
      </el-container>
  </div>
</template>

<script>
import NavMenu from '@/mock/NavMenu'
// @ is an alias to /src
import MenuList from '@/components/Menulist'
export default {
  name: 'mains',
  components: {
    MenuList
  },
  data(){
    return {
        isCollapse: false,
        List:NavMenu
    }
  },
  mounted(){
      // this.renderMenu(NavMenu)
     console.log(NavMenu)
  },
  methods:{
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      },
      // renderMenu (data) {
      //    return 
      // }
  }
}
</script>
<style>
  .el-header, .el-footer {
    background-color: #B3C0D1;
    color: #333;
    /* text-align: center; */
    line-height: 60px;
  }
  
  .el-aside {
    background-color: #D3DCE6;
    color: #333;
    text-align: center;
    /* line-height: 200px; */
  }
  
  .el-main {
    background-color: #E9EEF3;
    color: #333;
    text-align: center;
    min-height: calc(100vh - 120px)
    /* line-height: 160px; */
  }
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 280px;
    /* min-height: 400px; */
  }
  .logo{
     height:60px;
     line-height:60px;
     display: flex;
     justify-content: center;
     align-items: center;
  }
</style>

3:递归组件(MenuList)

<template>
    <div>
        <el-menu  class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse" >
            <template v-for="(item,index) of list" >
                <el-submenu :index="index+''" v-if="item.children" :key="index">
                    <template slot="title">
                        <i :class="item.icon"></i>
                        <span>{{item.title}}</span>
                    </template>
                    <menu-list :list="item.children"></menu-list>   <!--递归调用-->
                </el-submenu>
                <el-menu-item :index="index+''"  v-else :key="index">
                    <i :class="item.icon"></i>
                    <span slot="title">{{item.title}}</span>
                </el-menu-item>
            </template> 
         </el-menu> 
    </div>
</template>
<script>
export default {
    name:'MenuList',
    props: {
        list: Array,
        isCollapse:Boolean
    },
    methods:{
        handleOpen(key, keyPath) {
            console.log(key, keyPath);
        },
        handleClose(key, keyPath) {
            console.log(key, keyPath);
        },
    }
}
</script>
<style>

</style>

注意 

el-menu 和 子级元素 之间不能加div 最初设想是el-menu 在父组件中  子组件负责动态生成其子元素,发现不可行原因在于template下面层级只允许出现一个子级元素,会出现收缩菜单的时候字体无法隐藏 

所以解决办法是把el-menu 挪到递归组件中来!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
假设我们有以下的树形菜单结构: ``` - 菜单1 - 子菜单1.1 - 子菜单1.2 - 孙菜单1.2.1 - 孙菜单1.2.2 - 菜单2 - 子菜单2.1 ``` 我们可以定义一个 Menu 类来表示每个菜单项: ```java class Menu { String name; List<Menu> children; public Menu(String name) { this.name = name; children = new ArrayList<>(); } // 添加子菜单 public void addChild(Menu menu) { children.add(menu); } } ``` 接下来,我们可以使用递归的方式来打印整个树形菜单: ```java class TreeMenu { public static void printMenu(Menu menu, int level) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < level; i++) { sb.append("-"); } sb.append(menu.name); System.out.println(sb.toString()); // 递归打印子菜单 for (Menu childMenu : menu.children) { printMenu(childMenu, level + 1); } } } public class Main { public static void main(String[] args) { // 构建树形菜单 Menu menu1 = new Menu("菜单1"); Menu menu11 = new Menu("子菜单1.1"); Menu menu12 = new Menu("子菜单1.2"); Menu menu121 = new Menu("孙菜单1.2.1"); Menu menu122 = new Menu("孙菜单1.2.2"); menu12.addChild(menu121); menu12.addChild(menu122); menu1.addChild(menu11); menu1.addChild(menu12); Menu menu2 = new Menu("菜单2"); Menu menu21 = new Menu("子菜单2.1"); menu2.addChild(menu21); // 打印树形菜单 TreeMenu.printMenu(menu1, 0); TreeMenu.printMenu(menu2, 0); } } ``` 输出结果为: ``` -菜单1 --子菜单1.1 --子菜单1.2 ---孙菜单1.2.1 ---孙菜单1.2.2 -菜单2 --子菜单2.1 ``` 我们通过递归遍历整棵树,按照菜单层级打印每个菜单项的名称,并加上相应的缩进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值