侧边栏导航菜单在平常 CMS 管理平台开发中很常见,最近在产品开发中就遇到难题:
公司采用的是 vue + element 技术栈,element 文档中 NavMenu 是写死的,而不是通过数据渲染的,菜单多、层级深的时候,就很鸡肋...
再参考 此链接 后,再结合自己需求,组装成 kgMenu 组件
kgMenu 里面封装 kgSubMenu、kgMenuGroup、kgMenuItem 三个基础组件
kgMenuItem.vue
// kgMenuItem
<template>
<el-menu-item :index="menu.index" :route="menu.route.path">
<template>
<i :class="menu.icon"></i><span slot="title">{{ menu.lable }}</span>
</template>
</el-menu-item>
</template>
<script>
export default {
name: 'kgMenuItem',
props: {
menu: {
type: Object
}
},
data () {
return {}
}
}
</script>
kgSubMenu.vue
// kgSubMenu.vue
<template>
<el-submenu v-if="menu.type === 'submenu'" :index="menu.index">
<template slot="title" v-if="menu.lable !== null">
<i :class="menu.icon"></i>
<span slot="title">{{ menu.lable }}</span>
</template>
<template v-if="menu.childs !== null">
<template v-for="menuItem in menu.childs">
<template v-if="menuItem.type === 'item'">
<kg-menu-item :menu="menuItem" :key="menuItem.id"></kg-menu-item>
</template>
<template v-if="menuItem.type === 'submenu'">
<kg-sub-menu :menu="menuItem" :key="menuItem.id"></kg-sub-menu>
</template>
<template v-if="menuItem.type === 'group'">
<kg-menu-group :menu="menuItem" :key="menuItem.id"></kg-menu-group>
</template>
</template>
</template>
</el-submenu>
</template>
<script>
import kgMenuItem from './kgMenuItem'
import kgMenuGroup from './kgMenuGroup'
export default {
name: 'kgSubMenu',
props: {
menu: {
type: Object
}
},
components: {kgMenuItem, kgMenuGroup},
data () {
return {}
}
}
</script>
kgMenuGroup.vue
// kgMenuGroup.vue
<template>
<el-menu-item-group>
<template slot="title" v-if="menu.lable !== null">
<i :class="menu.icon"></i>
<span slot="title">{{ menu.lable }}</span>
</template>
<template v-if="menu.childs !== null">
<template v-for="menuItem in menu.childs">
<template v-if="menuItem.type === 'item'">
<kg-menu-item :menu="menuItem" :key="menuItem.id"></kg-menu-item>
</template>
<template v-if="menuItem.type === 'submenu'">
<kg-sub-menu :menu="menuItem" :key="menuItem.id"></kg-sub-menu>
</template>
</template>
</template>
</el-menu-item-group>
</template>
<script>
import kgMenuItem from './kgMenuItem'
import kgSubMenu from './kgSubMenu'
export default {
name: 'kgMenuGroup',
props: {
menu: {
type: Object
}
},
components: {kgMenuItem, kgSubMenu},
data () {
return {}
}
}
</script>
kgMenu.vue
<template>
<el-menu
:background-color="settings.backgroundColor"
:text-color="settings.textColor"
:router="settings.router"
:active-text-color="settings.activeTextColor">
<template v-for="menuItem in leftMenus">
<template v-if="menuItem.type === 'item'">
<kg-menu-item :menu="menuItem" :key="menuItem.id"></kg-menu-item>
</template>
<template v-if="menuItem.type === 'submenu'">
<kg-sub-menu :menu="menuItem" :key="menuItem.id"></kg-sub-menu>
</template>
<template v-if="menuItem.type === 'group'">
<kg-menu-group :menu="menuItem" :key="menuItem.id"></kg-menu-group>
</template>
</template>
</el-menu>
</template>
<script>
import kgMenuItem from './kgMenuItem'
import kgSubMenu from './kgSubMenu'
import kgMenuGroup from './kgMenuGroup'
export default {
name: 'kgMenu',
props: {
leftMenus: {
type: Array
},
settings: {
type: Object
}
},
components: {kgMenuItem, kgSubMenu},
data () {
return {}
}
}
</script>
封装好后,在需要调用的调用 kgMenu 即可, 通过 props 传递菜单数据 leftMenus 和 菜单设置 settings,
\\ index.vue
<template>
<div>
...
<kg-menu :leftMenus="menuList" :settings="menuSetting"></kg-menu>
...
</div>
</template>
<script>
import kgMenu from '../kgMenu'
export default {
components: {kgMenu},
date () {
return {
menuSetting: {
backgroundColor: '#333743',
textColor: '#909399',
activeTextColor: '#909399',
defaultOpeneds: [],
uniqueOpened: true,
router: true,
collapseTransition: true
},
menuList: [
{
id: 0,
type: 'item',
index: 'home',
lable: '首页',
icon: 'el-icon-circle-plus-outline',
route: {
type: 'inner',
path: {name: 'KgGainIframe', params: {'postfix': 'D2R'}}
}
},
{
id: 1,
type: 'submenu',
index: 'news',
lable: '新闻',
icon: 'ic-association-analysis',
childs: [
{
id: 0,
type: 'item',
index: 'addNews',
lable: '发布新闻',
route: {
type: 'inner',
path: {name: 'KgAddNews'}
}
},
{
id: 1,
type: 'item',
index: 'newsList',
lable: '新闻列表',
route: {
type: 'inner',
path: {name: 'KgNewsList'}
}
}
]
}
...
]
}
}
}
</script>