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

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/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 挪到递归组件中来!

更多推荐

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