前言:vue 项目中,在使用 element-ui 导航菜单组件时,官方文档给出的示例,是已知菜单项静态写死的 。然而在日常开发中,要求从后端请求拿到菜单数据,再由前端去 实现菜单的动态渲染生成 ,这里对具体实现过程做一个总结 。


  • vuex 中存放 Menus ,模拟后端请求到的数据
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        Menus: [{
                "path": "/home",
                "name": "首页",
                "icon": "el-icon-s-home"
            },
            {
                "path": "/user",
                "name": "用户管理",
                "icon": "el-icon-user",
                "children": [{
                        "path": "/user/profile",
                        "name": "用户信息",
                        "icon": null,
                    },
                    {
                        "path": "/user/role",
                        "name": "角色配置",
                        "icon": null,
                    }
                ]
            },
            {
                "path": "/content",
                "name": "内容管理",
                "icon": "el-icon-tickets",
                "children": [{
                        "path": "/content/department",
                        "name": "就业部类",
                        "icon": null
                    },
                    {
                        "path": "/content/student",
                        "name": "学生类",
                        "icon": null,
                        "children": [{
                            "path": "/content/student/graduateInfo",
                            "name": "毕业生信息",
                            "icon": null
                        }]
                    },
                    {
                        "path": "/content/enterprise",
                        "name": "企业类",
                        "icon": null
                    }
                ]
            },
            {
                "path": "/system",
                "name": "系统管理",
                "icon": "el-icon-s-tools",
                "children": [{
                        "path": "/system/run",
                        "name": "运行情况",
                        "icon": null
                    },
                    {
                        "path": "/system/data",
                        "name": "备份恢复数据库",
                        "icon": null
                    },
                    {
                        "path": "/system/log",
                        "name": "操作日志",
                        "icon": null
                    }
                ]
            },
            {
                "path": "/link",
                "name": "链接",
                "icon": "el-icon-paperclip"
            }
        ]
    },
    mutations: {},
    actions: {},
    modules: {}
})
  • 外层 SideMenu 组件
<template>
  <div>
    <el-menu router
      class="el-menu-vertical-demo"
      unique-opened
      default-active="/home">
      <Menus :routerList="this.$store.state.Menus"></Menus>
    </el-menu>
  </div>
</template>

<script>
import Menus from './menus.vue';
export default {
  name: 'SideMenu',
  components: {
    Menus
  }
}
</script>

<style  lang="css">
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
</style>
  • 内层 Menus 组件

<template>
  <div>
    <template v-for="item in routerList">
      <el-submenu v-if="item.hasOwnProperty('children')&&item.children.length>0"
        :key="item.path"
        :index="item.path">
        <template slot="title"
          style="padding-left:10px">
          <i class="el-icon-menu"></i>
          <span slot="title">{{ item.name}}</span>
        </template>
        <!--  如果有子级数据使用递归组件 -->
        <Menus :routerList="item.children"></Menus>
      </el-submenu>
      <el-menu-item v-else
        :index="item.path"
        :key="item.path">
        <i :class="item.icon"></i>
        <span>{{item.name}}</span>
      </el-menu-item>
    </template>
  </div>
</template>

<script>
export default {
  props: ['routerList'],
  name: 'Menus' 
}
</script>

<style  lang="css">
.el-menu--collapse span,
.el-menu--collapse i.el-submenu__icon-arrow {
  height: 0;
  width: 0;
  overflow: hidden;
  visibility: hidden;
  display: inline-block;
}
</style>
  • 布局 App 组件中使用
<template>
  <div id="app">
    <el-container>
      <el-header>
        <Top></Top>
      </el-header>
      <el-container>
        <el-aside width="200px">
          <Side-Menu></Side-Menu>
        </el-aside>
        <el-main>
          <el-empty description="暂无渲染内容..."></el-empty>
          <router-view />
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import Top from '@/components/top.vue'
import SideMenu from '@/components/sideMenu.vue'
export default {
  name: 'App',
  components: {
    Top,
    SideMenu
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  font-family: "楷体";
  font-size: 16px;
}
.el-header {
  background-color: #b3c0d1;
  color: #333;
  text-align: center;
  line-height: 60px;
}
.el-aside {
  color: #333;
  height: calc(100vh - 60px);
}
.el-main {
  background-color: #e9eef3;
  color: #333;
  height: calc(100vh - 60px);
}
.el-empty {
  width: 100%;
  height: 100%;
}
body > .el-container {
  margin-bottom: 40px;
}
</style>

【 完整示例查看:https://gitee.com/wu241617/element-dynamic-menu​​​​​​​ 

Logo

前往低代码交流专区

更多推荐