基于el-menu,用递归实现动态n级菜单

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于el-menu,用递归实现动态n级菜单相关的知识,希望对你有一定的参考价值。

参考技术A el-menu 由 子菜单、菜单项组成(先不考虑分组的问题),子菜单可以看做是树枝,菜单项可以看做是树叶,子菜单可以包含子菜单和菜单项,菜单项不能包含。

一种常见的分组结构,可以加上icon的信息。

准备工作完成后,我们写一个递归组件即可

父组件

这样就可以实现基于json渲染的n级分组菜单了。

基于element-ui封装侧边栏菜单,可无限展开

一、思路

利用组件递归思想

二、代码实现

index文件

<template>
  <div class="side-menu-wrapper">
    <el-aside width="100%">
      <el-menu :default-openeds="defaultOpends" :default-active="defaultActive">
        <template v-for="(item, index) in sideDate">
          <template v-if="item.children && item.children.length">
            <SideMenuItem :key="index" :list="item.children" :index="String(index)" :sub-label="item.label"/>
          </template>
          <template v-else>
            <el-menu-item :index="String(index)" :key="index" @click="handleClick(item)">
              <i class="el-icon-setting"></i>
              <span slot="title"> item.label </span>
            </el-menu-item>
          </template>
        </template>
      </el-menu>
    </el-aside>
  </div>
</template>

<script>
import SideMenuItem from './sideMenuItem'

export default 
  name: 'index',
  components: 
    SideMenuItem
  ,
  props: 
    sideDate: 
      // 渲染的数据
      type: Array
    ,
    defaultOpends: 
      // 默认展开的项
      type: Array
    ,
    defaultActive: 
      // 默认激活的菜单项
      type: String,
      default: '0-0'
    
  ,
  methods: 
    handleClick(item) 
      if (item.name === this.$route.name) 
        return
      
      this.$router.push(
        name: item.name
      )
    
  

</script>

<style lang="scss" scoped>
@import "../../style/mixin";

.side-menu-wrapper 
  width: 100%;
  height: 100%;

  /deep/ .el-aside 
    height: 100%;
    border-radius: 10px;
    border: 1px solid $bgColor;

    & > ul 
      width: 100%;
      height: 100%;
      border-radius: 10px;
      border: 1px solid $bgColor;

      .el-submenu__title 
        font-size: 18px;
        color: $fontColor;
      

      .el-menu-item 
        font-size: 18px;
        color: $fontColor;
      

      .is-active 
        color: #1890ff;
        //background-color: #bae7ff;
      

      .el-submenu__icon-arrow 
        font-size: 16px;
        color: $fontColor;
      
    
  

</style>

menuItem组件

<template>
  <el-submenu :index="index">
    <template slot="title"><i class="el-icon-message"></i> subLabel </template>
    <template v-for="(subItem, subIndex) in list">
      <template v-if=" subItem.children && subItem.children.length">
      <!--  组件自身递归调用      -->
        <sideMenuItem :index="`$index-$subIndex`" :key="`$index-$subIndex`" :list="subItem.children" :sub-label="subItem.label"/>
      </template>
      <template v-else>
        <el-menu-item :index="`$index-$subIndex`" :key="`$index-$subIndex`" @click="handleClick(subItem)">
          <i class="el-icon-setting"></i>
          <span slot="title"> subItem.label </span>
        </el-menu-item>
      </template>
    </template>
  </el-submenu>
</template>

<script>
export default 
  name: 'sideMenuItem',
  props: 
    list: 
      type: Array,
      default: () => []
    ,
    index: String,
    subLabel: String
  ,
  methods: 
    handleClick(item) 
      if (item.name === this.$route.name) 
        return
      
      this.$router.push(
        name: item.name
      )
    
  

</script>

<style lang="scss" scoped>
/deep/ .el-menu-item 
  font-size: 16px;

</style>

三、使用

<template>
  <div>
    <SideMenu :sideDate="list"  :defaultOpends="['0']"/>
  </div>
</template>
<script>
import SideMenu from '@/components/sideMenu'
export default 
  components: 
    SideMenu
  ,
  data() 
    return 
      list: [
        
          label: '海水水质',
          name: 'test1',
          icon: '',
          path: 'test1',
          children: [
            
              label: '全国总体情况1',
              name: '',
              icon: '',
              path: '',
              children: [
                
                  label: '测试',
                  name: '',
                  icon: '',
                  path: '',
                  children: [
                    
                      label: '测试',
                      name: '',
                      icon: '',
                      path: ''
                    
                  ]
                
              ]
            ,
            
              label: '全国总体情况2',
              name: '',
              icon: '',
              path: '',
              children: [
                
                  label: '测试',
                  name: '',
                  icon: '',
                  path: ''
                
              ]
            
          ]
        ,
        
          label: '海水水质',
          name: 'test1',
          icon: '',
          path: 'test1',
          children: [
            
              label: '全国总体情况3',
              name: '',
              icon: '',
              path: '',
              children: [
                
                  label: '测试',
                  name: '',
                  icon: '',
                  path: ''
                
              ]
            ,
            
              label: '全国总体情况4',
              name: '',
              icon: '',
              path: '',
              children: [
                
                  label: '测试',
                  name: '',
                  icon: '',
                  path: ''
                
              ]
            
          ]
        ,
        
          label: '入海河流',
          name: 'test1',
          icon: '',
          path: 'test1'
        
      ]
    ;
  
;
</script>
<style lang="scss" scoped>
@import "../style/mixin.scss";

.content 
  @include content();

</style>

效果

以上是关于基于el-menu,用递归实现动态n级菜单的主要内容,如果未能解决你的问题,请参考以下文章

vue element-ui 左侧菜单栏 el-menu属性实现动态菜单

动态菜单栏

基于element-ui封装侧边栏菜单,可无限展开

基于element-ui封装侧边栏菜单,可无限展开

基于element-ui封装侧边栏菜单,可无限展开

想用java实现一个无限级树型菜单,数据库是这样设计的:id,pid(父id),name.用递归调用,要一次性加载.