目前就4级菜单,所以没有抽取组件优化菜单代码,可以自行优化。
版本说明:
"dependencies": {
"element-plus": "^2.2.17",
"vue": "^3.2.39",
"vue-router": "^4.1.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.1.0",
"fast-glob": "^3.2.12",
"vite": "^3.1.0",
"vite-plugin-svg-icons": "^2.0.1"
}
实例见下图:
实现逻辑,开始想使用element plus的自动路径,出了很多问题,最后还是自行拼了完整路径。
main.js引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/router_config'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import SvgIcon from './components/icon/icon-component.vue'//svg图相关
import 'virtual:svg-icons-register'//svg图相关
createApp(App)
.component('svg-icon', SvgIcon)
.use(ElementPlus)
.use(router)
.mount('#app')
router_config.js
import { createRouter, createWebHistory } from 'vue-router'
import layout from '../layout/layout_index.vue'
import notFound from './public/not_found.vue'
const routes = [
{
path: '/',
component: layout,
redirect: '/home',
children: [
{
path: 'home',
component: () => import('../views/home.vue')
},
{
path: 'internet',
redirect: '/internet/status',
children: [
{
path: 'status',
redirect: '/internet/status/dsl',
children: [
{
path: 'dsl',
component: () => import('../views/internet/status/dsl.vue')
},
{
path: 'eth',
component: () => import('../views/internet/status/eth.vue')
},
{
path: '3g',
component: () => import('../views/internet/status/3g.vue')
},
{
path: '6rd',
component: () => import('../views/internet/status/6rd.vue')
},
]
},
{
path: 'wan',
component: () => import('../views/internet/wan.vue')
},
{
path: 'qos',
component: () => import('../views/internet/qos.vue')
},
{
path: 'security',
component: () => import('../views/internet/security.vue')
},
]
}
]
},
{
path: '/:pathMatch(.*)*', name: 'NotFound', component: notFound
},
];
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
App.vue
<script setup>
</script>
<template>
<router-view></router-view>
</template>
<style scoped>
</style>
layout_index.vue
<template>
<el-container class="common-layout" style="height: 500px">
<el-header height="55px">
<span class="custom-text-force">I am header 3333333333333333333333333.</span>
</el-header>
<el-container style="max-width: 1024px;">
<el-aside style="max-width: 200px;height: 100%">
<el-scrollbar>
<el-menu router>
<template v-for="(obj, index) in menuData">
<!-- home页面没有子集菜单 -->
<template v-if="obj.routePath == 'home'">
<el-menu-item route :index="'/' + obj.routePath">
<template #title>
<div :title="obj.name" class="custom-div-menu">
<svg-icon :iconName="obj.icon" iconClass="icon-calss-menu"></svg-icon>
{{obj.name}}
</div>
</template>
</el-menu-item>
</template>
<!-- 一级菜单,最多4级菜单 -->
<el-sub-menu v-else :index="obj.routePath">
<template #title>
<div :title="obj.name" class="custom-div-menu">
<svg-icon :iconName="obj.icon" iconClass="icon-calss-menu"></svg-icon>
{{obj.name}}
</div>
</template>
<template v-if="obj.children" v-for="(obj2, index2) in obj.children">
<template v-if="!obj2.children">
<el-menu-item route :index="'/' + obj.routePath + '/' + obj2.routePath">
<template #title>{{obj2.name}}</template>
</el-menu-item>
</template>
<template v-else>
<el-sub-menu :index="'/' + obj.routePath + '/' + obj2.routePath">
<template #title>{{obj2.name}}</template>
<template v-for="(obj3, index3) in obj2.children">
<template v-if="!obj3.children">
<el-menu-item route :index="'/' + obj.routePath + '/' + obj2.routePath + '/' + obj3.routePath">
<template #title>{{obj3.name}}</template>
</el-menu-item>
</template>
<template v-else>
<el-sub-menu :index="'/' + obj.routePath + '/' + obj2.routePath + '/' + obj3.routePath">
<template #title>{{obj3.name}}</template>
<template v-for="(obj4, index4) in obj3.children">
<el-menu-item :index="'/' + obj.routePath + '/' + obj2.routePath + '/' + obj3.routePath + '/' + obj4.routePath">
<template #title>{{obj4.name}}</template>
</el-menu-item>
</template>
</el-sub-menu>
</template>
</template>
</el-sub-menu>
</template>
</template>
</el-sub-menu>
</template>
</el-menu>
</el-scrollbar>
</el-aside>
<el-container>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
<el-footer width="100%">版权所有</el-footer>
</el-container>
</template>
<script>
import { menuConfig } from './menu_config.js'
export default {
name: 'menu_layout',
data() {
return {
menuData: menuConfig
}
},
props: {
},
methods: {
}
}
</script>
<style scoped>
.icon-calss-menu {
height: 2rem;
width: 2rem;
margin-bottom: -0.7rem;
}
.custom-div-menu {
width: 132px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
/* display: block; */
}
</style>
菜单配置文件
menu_config.js
const menuConfig = [
{
name:'Home',
routePath: 'home',
icon: 'caiselijia'
},
{
name:'Interent',
routePath: 'internet',
icon: 'caisehuiyi',
children: [
{
name:'Status',
routePath: 'status',
children: [
{
name:'DSL',
routePath: 'dsl',
},
{
name:'Ethernet',
routePath: 'eth'
},
{
name:'3G',
routePath: '3g'
},
{
name:'6RD',
routePath: '6rd'
}
]
},
{
name:'WAN',
routePath: 'wan'
},
{
name:'QoS',
routePath: 'qos'
},
{
name:'Security',
routePath: 'security'
}
]
},
{
name:'Local Network',
routePath: 'network',
icon: 'xiyiji',
children: [
{
name:'Status',
routePath: 'status'
},
{
name:'WLAN',
routePath: 'wlan'
}
]
},
{
name:'VoIP',
routePath: 'voip',
icon: 'xiyiji',
children: [
{
name:'Status',
routePath: 'status'
},
{
name:'Basic',
routePath: 'wlan'
}
]
},
{
name:'Management & Diagnosis',
routePath: 'management',
icon: 'yizi',
children: [
{
name:'Status',
routePath: 'status'
},
{
name:'Account Management',
routePath: 'account'
}
]
},
]
export {menuConfig}