[Vue]ElementUI 多级菜单组件封装

基于ElementUI的项目,由于原本的navbar是写死的,所以自己封装菜单组件,让他能够不限子菜单层级渲染

目录:
在这里插入图片描述

  1. 数据结构
menuList: [
 {
   id: 0,
   type: "item",
   index: "home",
   lable: "首页",
   icon: "el-icon-circle-plus-outline",
   route: {
     type: "inner",
     path: { name: "GainIframe", params: { id: "2" } }
   }
 },
 {
   id: 1,
   type: "submenu",
   index: "news",
   lable: "系统管理",
   icon: "el-icon-circle-plus-outline",
   childs: [
     {
       id: 2,
       type: "item",
       index: "addMenu",
       lable: "菜单管理",
       icon: "el-icon-circle-plus-outline",
       route: {
         type: "inner",
         path: { name: "AddNews" }
       }
     },
     {
       id: 3,
       type: "submenu",
       index: "rolesList",
       lable: "角色管理",
       icon: "el-icon-circle-plus-outline",
       route: {
         type: "inner",
         path: { name: "GainIframe", params: { id: "2" } }
       },
       childs: [
         {
           id: 4,
           type: "item",
           index: "submenu",
           lable: "用户管理",
           icon: "el-icon-circle-plus-outline",
           route: {
             type: "inner",
             path: { name: "GainIframe", params: { id: "2" } }
           }
         }
       ]
     }
   ]
 },
 {
   id: 5,
   type: "submenu",
   index: "news",
   lable: "新闻",
   icon: "el-icon-circle-plus-outline",
   childs: [
     {
       id: 6,
       type: "item",
       index: "addNews",
       lable: "发布新闻",
       icon: "el-icon-circle-plus-outline",
       route: {
         type: "inner",
         path: { name: "AddNews" }
       }
     },
     {
       id: 7,
       type: "submenu",
       index: "newsList",
       lable: "新闻列表",
       icon: "el-icon-circle-plus-outline",
       route: {
         type: "inner",
         path: { name: "NewsList" }
       },
       childs: [
         {
           id: 8,
           type: "submenu",
           index: "NewsAdd",
           lable: "新闻添加",
           icon: "el-icon-circle-plus-outline",
           route: {
             type: "inner",
             path: { name: "NewsList" }
           },
           childs: [
             {
               id: 9,
               type: "submenu",
               index: "addNews",
               lable: "发布新闻",
               icon: "el-icon-circle-plus-outline",
               route: {
                 type: "inner",
                 path: { name: "AddNews" }
               },
               childs: [
                 {
                   id: 10,
                   type: "item",
                   index: "NewsPush",
                   lable: "新闻发布",
                   icon: "el-icon-circle-plus-outline",
                   route: {
                     type: "inner",
                     path: { name: "AddNews" }
                   }
                 }
               ]
             }
           ]
         }
       ]
     }
   ]
 }
]
  1. MenuGroup.vue
<template>
   <el-menu-item-group>
    <template slot="title" v-if="menu.lable!== null">
      <i :class="menu.icon"></i>
      <span slot="title">{{ menu.lable }}</span>
    </template>
    <template v-if="menu.childs!== null">
      <template v-for="menuItem in menu.childs">

        <template v-if="menuItem.type === 'item'">
          <menu-item :menu="menuItem" :key="menuItem.id"></menu-item>
        </template>

        <template v-if="menuItem.type === 'submenu'">
          <sub-menu :menu="menuItem" :key="menuItem.id"></sub-menu>
        </template>

      </template>
    </template>

  </el-menu-item-group>
</template>
<script>
import MenuItem from './MenuItem.vue'
import SubMenu from './subMenu.vue'

export default {
    name:'MenuGroup',
    props: {
        menu: {
        type: Object
        }
    },
    components: {MenuItem,SubMenu},
    data () {
        return {

        }
    }
}
</script>
<style>
</style>
  1. subMenu.vue
<template>
  <el-submenu v-if="menu.type === 'submenu'" :index="menu.index">

    <template slot="title" v-if="menu.lable !== null">
      <i :class="menu.icon"></i>
      <span slot="title">{{ menu.lable }}</span>
    </template>

    <template v-if="menu.childs !== null">

      <template v-for="menuItem in menu.childs">

        <template v-if="menuItem.type === 'item'">
          <menu-item :menu="menuItem" :key="menuItem.id"></menu-item>
        </template>

        <template v-if="menuItem.type === 'submenu'">
          <sub-menu :menu="menuItem" :key="menuItem.id"></sub-menu>
        </template>

        <template v-if="menuItem.type === 'group'">
          <menu-group :menu="menuItem" :key="menuItem.id"></menu-group>
        </template>

      </template>
    </template>
  </el-submenu>
</template> 
<script>
import MenuItem from "./MenuItem.vue";
import MenuGroup from "./MenuGroup.vue"; 
export default {
  name: "subMenu",
  props: {
    menu: {
      type: Object
    }
  },
  components: { MenuItem, MenuGroup },
  data() {
    return {};
  }
};
</script> 
<style>
</style>
  1. MenuItem.vue
<template>
  <el-menu-item :index="menu.index" :route="menu.route.path">
    <template>
      <i :class="menu.icon"></i><span slot="title">{{ menu.lable}}</span>
    </template>
  </el-menu-item>
</template>
<script>
export default {
    name:'MenuItem',
    props:{
      menu:{
        type:Object
      }
    },
    data(){
      return {}
    }    
}
</script> 
<style> 
</style>
  1. Menu.vue
<template>
  <div>
    <!-- <el-radio-group v-model="isCollapse">
      <el-radio-button :label="false">展开</el-radio-button>
      <el-radio-button :label="true">收起</el-radio-button>
    </el-radio-group>  -->
    <el-menu
      default-active="1-3-1"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      :collapse="isCollapse"
      :background-color="menuSetting.backgroundColor"
      :text-color="menuSetting.textColor"
      :active-text-color="menuSetting.activeTextColor"
      :unique-opened="menuSetting.uniqueOpened"
      :router="menuSetting.router"
    >
      <template v-for="menuItem in menuList">
        <template v-if="menuItem.type === 'item'">
          <menu-item :menu="menuItem" :key="menuItem.id"></menu-item>
        </template>
        <template v-if="menuItem.type === 'submenu'">
          <sub-menu :menu="menuItem" :key="menuItem.id"></sub-menu>
        </template>
        <template v-if="menuItem.type === 'group'">
          <menu-group :menu="menuItem" :key="menuItem.id"></menu-group>
        </template>
      </template>
    </el-menu>
  </div>
</template>
<script>
import MenuItem from "./subcomponents/MenuItem.vue";
import SubMenu from "./subcomponents/subMenu.vue";
import MenuGroup from "./subcomponents/MenuGroup.vue";
export default {
  components: { MenuItem, SubMenu, MenuGroup },
  data() {
    return {
      isCollapse: false, //菜单切换 
      menuSetting: {
        backgroundColor: "#842D7D",
        textColor: "#fff",
        activeTextColor: "#ffd04b",
        defaultOpeneds: [],
        uniqueOpened: true,
        router: true,   //直接使用 index 进行路由跳转
        collapseTransition: true
      }, 
      menuList: [
        {
          id: 0,
          type: "item",
          index: "home",
          lable: "首页",
          icon: "el-icon-circle-plus-outline",
          route: {
            type: "inner",
            path: { name: "GainIframe", params: { id: "2" } }
          }
        },
        {
          id: 1,
          type: "submenu",
          index: "news",
          lable: "系统管理",
          icon: "el-icon-circle-plus-outline",
          childs: [
            {
              id: 2,
              type: "item",
              index: "addMenu",
              lable: "菜单管理",
              icon: "el-icon-circle-plus-outline",
              route: {
                type: "inner",
                path: { name: "AddNews" }
              }
            },
            {
              id: 3,
              type: "submenu",
              index: "rolesList",
              lable: "角色管理",
              icon: "el-icon-circle-plus-outline",
              route: {
                type: "inner",
                path: { name: "GainIframe", params: { id: "2" } }
              },
              childs: [
                {
                  id: 4,
                  type: "item",
                  index: "submenu",
                  lable: "用户管理",
                  icon: "el-icon-circle-plus-outline",
                  route: {
                    type: "inner",
                    path: { name: "GainIframe", params: { id: "2" } }
                  }
                }
              ]
            }
          ]
        } 
      ]
    };
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    }
  }
};
</script> 
<style> 
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 880px;
}  
</style>
  1. 效果:
    在这里插入图片描述

参考链接:

elementUI 多级菜单动态渲染

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值