前言

前一篇文章中有说到,动态路由配合动态菜单使用有奇效
我在这里在做一篇动态菜单的博客
首先来说,动态菜单的核心便是编写一个递归组件,以达到根据后端传递过来的菜单集合自动生成菜单

组件介绍

首先这个递归组件是来自ETZHOU的手笔,我后续根据我自己的需求进行了调整,各位在使用的时候可以根据自身需求去调整内容.

1、子组件SidebarItem.vue

<template>
  <div v-if="item.children">
    <template v-if="item.children.length == 0">
        <el-menu-item :index="itemPath+'/'+item.path" :disabled="item.delFlag ==1">
          <i :class="item.icon"></i>
          <span>{{item.name}}</span>
        </el-menu-item>
    </template>

    <el-submenu v-else :index="itemPath+'/'+item.path">
      <template slot="title" >
        <i :class="item.icon"></i>
        <span>{{item.name}}</span>
      </template>

      <template v-for="child in item.children">
        <sidebar-item
          v-if="child.children&&child.children.length>0"
          :item="child"
          :rootName="rootName" :rootPath="itemPath"
          :key="child.path"/>
        <el-menu-item v-else :key="child.path" :index="itemPath+'/'+child.path" :disabled="child.delFlag == 1">
          <i :class="child.icon"></i>
          <span>{{child.name}}</span>
        </el-menu-item>
      </template>
    </el-submenu>
  </div>
  <div v-else>
      <el-menu-item :index="itemPath+'/'+item.path" :disabled="item.delFlag ==1">
        <i :class="item.icon"></i>
        <span>{{item.name}}</span>
      </el-menu-item>
  </div>
</template>

<script>
export default {
  name: 'SidebarItem',
  props: {
    item: {
      type: Object,
      required: true
    },
    rootName: {
      type: String,
      required: true
    },
    rootPath: {
      type: String,
      required: true
    }
  },
  data(){
    return{
      itemPath:''
    }
  },
  created() {
    this.itemPath = this.rootPath +'/'+ this.item.path
  }
}
</script>

子组件是动态菜单的核心逻辑,通过v-if和v-else、v-else-if操作判断菜单是否还有下层

2、父组件Sidebar.vue

<template>
  <div class="sidebar-container">
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu style="font: 20px '楷体'; "
        default-active="2"
        class="el-menu-vertical-demo"
        unique-opened
        router
        background-color="#545c64"
        text-color="#bfcbd9"
        active-text-color="#409EFF">
      <sidebar-item v-for="menu in menuList" :key="menu.path" :item="menu" :rootName="''" :rootPath="''"/>
    </el-menu>
  </el-scrollbar>
  </div>
</template>
<script>
import SidebarItem from './SidebarItem.vue'
export default {
  name: 'Sidebar',
  components: { SidebarItem },
  props: {
    menuList: {
      type: Array,
      required: true
    }
  },
}
</script>
<style lang="less" scoped>
</style>

这里是父组件Sidebar.vue,将父组件引入你的页面中,给他传递对应的参数 menuList 便可成功引用
注意: 若直接复制代码不做修改请将父子组件放在同一个文件夹下,若是不在同一个文件夹请修改父组件中对子组件的引用。

引用

这里就更加简单了

<template>
    <div>
        <side-bar :menuList="menuList" />
    </div>
</template>

<script>
    import SideBar from "../SideBar/SideBar";
    import menu from "../../api/menu";
    export default {
        name: "backIndex",
        data(){
            return {
                menuList: [],
            }
        },
        methods:{
            queryMenus () {
                menu.getList().then(resp =>{
                    this.menuList = resp.data.data
                    //保存到仓库
                    this.$store.commit('addMenu', this.menuList)
                })
            },
        },
        mounted() {
            this.queryMenus()
        },
        components: { SideBar, },
    }
</script>

<style scoped>

</style>

直接从后端获取数据后直接传递进父组件中即可

后端支持

后端数据结构请看
vue动态路由
最后的后端支持

Logo

前往低代码交流专区

更多推荐