基于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>

效果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45150813/article/details/127007924