前言
大家好,我是腾讯云开发者社区的 Front_Yue,本篇文章将介绍如何封装element-ui中动态的el-menu组件,希望能够对大家有所帮助。
在前端开发中,我们经常需要使用到菜单组件来实现页面的导航和功能选择。而在项目中我们经常会将Element-UI作为组件库来方便我们的开发。但是,在实际项目中,我们经常会遇到需要动态生成菜单的场景,这时候我们就需要对el-menu进行封装,以便于我们更加灵活地使用和定制。
一、el-menu的基本用法
在这里我们我们主要讲解el-menu的用法,不再对element-ui进行说明。
el-menu提供水平和垂直菜单组件,可以通过设置el-menu-item和el-submenu来生成菜单项和子菜单。下面是一个简单的el-menu示例:
代码语言:html复制<template>
<el-menu default-active="1" class="el-menu-vertical-demo">
<el-menu-item index="1">
<i class="el-icon-menu"></i>
<span slot="title">菜单项1</span>
</el-menu-item>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">菜单项2</span>
</el-menu-item>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-menu"></i>
<span>子菜单1</span>
</template>
<el-menu-item index="3-1">子菜单项1</el-menu-item>
<el-menu-item index="3-2">子菜单项2</el-menu-item>
</el-submenu>
</el-menu>
</template>
通过上面的代码,我们可以看到el-menu
的基本用法。在el-menu
中,我们可以设置default-active
属性来指定默认选中的菜单项,class属性用于设置菜单的样式。
在el-menu
中,我们可以使用el-menu-item
和el-submenu
来生成菜单项和子菜单。其中,el-menu-item
的index属性用于设置菜单项的唯一标识,slot="title"用于设置菜单项的标题,el-submenu
中的template slot="title"用于设置子菜单的标题。在el-submenu
中,我们可以使用el-menu-item
来生成子菜单项。
二、封装动态el-menu
在实际项目开发中,我们经常需要动态生成菜单,而el-menu并没有提供直接的支持。因此,我们需要对el-menu进行封装,以便于我们更加灵活地使用和定制。
在封装el-menu之前,我们需要先明确一下需求。我们需要根据后台返回的菜单数据动态生成菜单,同时支持菜单项的选中和展开状态的保存。
1. 动态生成菜单
为了实现动态生成菜单,我们需要将菜单数据从后台获取到,并将其转换成el-menu所需的格式。通常情况下,我们可以将菜单数据的格式设计成如下所示:
代码语言:javascript复制[
{
"id": 1,
"name": "菜单1",
"icon": "el-icon-menu",
"url": "/menu1",
"children": [
{
"id": 11,
"name": "子菜单1-1",
"icon": "",
"url": "/menu1/1",
"children": []
},
{
"id": 12,
"name": "子菜单1-2",
"icon": "",
"url": "/menu1/2",
"children": []
}
]
},
{
"id": 2,
"name": "菜单2",
"icon": "el-icon-menu",
"url": "/menu2",
"children": []
}
]
通过上面的数据格式,我们可以看到每个菜单项都包含了id、name、icon、url和children等属性。其中,id用于唯一标识菜单项,name用于设置菜单项的标题,icon用于设置菜单项的图标,url用于设置菜单项的链接地址,children用于设置子菜单项。通过这样的数据格式,我们可以很方便地生成el-menu所需的菜单项和子菜单项。
接下来,我们就可以开始封装el-menu了。我们可以将el-menu封装成一个组件,命名为MenuCom
。在MenuCom中,我们可以通过props来接收菜单数据和默认选中的菜单项。
在MenuCom中,我们可以将菜单数据转换成el-menu所需的格式,并将其渲染成el-menu。在MenuCom中,我们需要通过watch
来监听菜单数据和默认选中的菜单项的变化,以便于更新菜单的状态。
MenuCom的代码实现:
代码语言:html复制<template>
<el-menu :default-active="defaultActive" :unique-opened="true" class="el-menu-vertical-demo" :collapse="collapse">
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<el-submenu :index="menu.id" :key="menu.id">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.name }}</span>
</template>
<template v-for="subMenu in menu.children">
<el-menu-item :index="subMenu.id" :key="subMenu.id">
<i :class="subMenu.icon"></i>
<span>{{ subMenu.name }}</span>
</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="menu.id" :key="menu.id">
<i :class="menu.icon"></i>
<span>{{ menu.name }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
代码语言:js复制<script>
export default {
name: 'MenuCom',
props: {
menuData: {
type: Array,
default: []
},
defaultActive: {
type: String,
default: ''
}
},
data() {
return {
collapse: false
}
},
watch: {
menuData: {
handler() {
this.$nextTick(() => {
this.$refs.menu.updateOpened()
})
},
deep: true
},
defaultActive() {
this.$nextTick(() => {
this.$refs.menu.updateActiveName()
})
}
}
}
</script>
在MenuCom中,我们首先使用el-menu来渲染菜单,通过default-active属性来设置默认选中的菜单项,通过unique-opened属性来设置只展开一个子菜单。
在MenuCom中,我们使用v-for来遍历菜单数据,通过v-if和v-else来判断菜单项是菜单还是子菜单。j接下来,我们使用el-submenu来生成子菜单,通过template slot="title"来设置子菜单的标题,通过v-for来遍历子菜单项。
在MenuCom中,我们使用el-menu-item来生成菜单项,通过index属性来设置菜单项的唯一标识。在MenuCom中,我们使用watch来监听菜单数据和默认选中的菜单项的变化,以便于更新菜单的状态。
2. 选中和展开状态的保存
作为动态菜单,最重要的是,在封装el-menu时,我们需要支持菜单项的选中和展开状态的保存。在el-menu中,我们可以通过default-active
属性来设置默认选中的菜单项,但是这种方式只能在页面刷新前生效,无法保存选中状态。因此,我们需要使用状态管理工具Vuex来保存菜单项的选中和展开状态。
在Vuex
中,我们可以使用state
来保存菜单项的选中和展开状态,使用mutation
来更新菜单项的选中和展开状态,使用getter
来获取菜单项的选中和展开状态。
在MenuCom中,我们可以通过Vuex来获取菜单项的选中和展开状态,并将其传递给el-menu。当菜单项被选中或展开时,我们可以通过mutation
来更新菜单项的选中和展开状态。
下面是Vuex的代码实现:
代码语言:javascript复制import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
activeMenu: '',
openedMenus: []
}
const mutations = {
setActiveMenu(state, activeMenu) {
state.activeMenu = activeMenu
},
setOpenedMenus(state, openedMenus) {
state.openedMenus = openedMenus
}
}
const getters = {
activeMenu: state => state.activeMenu,
openedMenus: state => state.openedMenus
}
export default new Vuex.Store({
state,
mutations,
getters
})
在Vuex
中,我们首先定义了state
来保存菜单项的选中和展开状态。
在mutations
中,我们定义了setActiveMenu
和setOpenedMenus
来更新菜单项的选中和展开状态。
在getters
中,我们定义了activeMenu
和openedMenus
来获取菜单项的选中和展开状态。
MenuCom完整代码示例:
代码语言:html复制<template>
<el-menu :default-active="activeMenu" :default-openeds="openedMenus" class="el-menu-vertical-demo" :collapse="collapse">
<template v-for="menu in menuData">
<template v-if="menu.children && menu.children.length > 0">
<el-submenu :index="menu.id" :key="menu.id" @click="handleSubmenuClick(menu.id)">
<template slot="title">
<i :class="menu.icon"></i>
<span>{{ menu.name }}</span>
</template>
<template v-for="subMenu in menu.children">
<el-menu-item :index="subMenu.id" :key="subMenu.id" @click="handleMenuItemClick(subMenu.id)">
<i :class="subMenu.icon"></i>
<span>{{ subMenu.name }}</span>
</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="menu.id" :key="menu.id" @click="handleMenuItemClick(menu.id)">
<i :class="menu.icon"></i>
<span>{{ menu.name }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
代码语言:js复制<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
name: 'MenuCom',
props: {
menuData: {
type: Array,
default: []
}
},
data() {
return {
collapse: false
}
},
computed: {
...mapGetters(['activeMenu', 'openedMenus'])
},
methods: {
...mapMutations(['setActiveMenu', 'setOpenedMenus']),
handleMenuItemClick(index) {
this.setActiveMenu(index)
},
handleSubmenuClick(index) {
const openedMenus = this.openedMenus.slice()
const indexInOpenedMenus = openedMenus.indexOf(index)
if (indexInOpenedMenus === -1) {
openedMenus.push(index)
} else {
openedMenus.splice(indexInOpenedMenus, 1)
}
this.setOpenedMenus(openedMenus)
}
}
}
</script>
在MenuCom中,我们首先使用Vuex来获取菜单项的选中和展开状态,同时我们使用@click来监听菜单项的点击事件,当菜单项被选中时,通过mutation来更新菜单项的选中状态。同理,使用@click来监听子菜单的点击事件,当子菜单被展开或收起时,我们通过mutation来更新菜单项的展开状态。
总结
本篇文章介绍了如何封装成动态的el-menu组件,文章介绍了组件初始示例,到如何根据动态菜单数据封装动态组件,我们通过封装组件,来提高在项目中的开发效率。通过本篇博客的学习,我们可以更好地理解Vue.js和Element UI的使用,以及如何封装组件来提高代码的复用性和可维护性。
最后,感谢腾讯云开发者社区小伙伴的陪伴,如果你喜欢我的博客内容,认可我的观点和经验分享,请点赞、收藏和评论,这将是对我最大的鼓励和支持。同时,也欢迎大家提出宝贵的意见和建议,让我能够更好地改进和完善我的博客。谢谢!
我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!