前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue2案例:封装动态的el-menu组件

Vue2案例:封装动态的el-menu组件

原创
作者头像
Front_Yue
修改2024-01-30 21:15:16
4701
修改2024-01-30 21:15:16
举报
文章被收录于专栏:码艺坊码艺坊

前言

大家好,我是腾讯云开发者社区的 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-itemel-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中,我们定义了setActiveMenusetOpenedMenus来更新菜单项的选中和展开状态。

getters中,我们定义了activeMenuopenedMenus来获取菜单项的选中和展开状态。

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腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 一、el-menu的基本用法
      • 二、封装动态el-menu
        • 1. 动态生成菜单
        • 2. 选中和展开状态的保存
    • 总结
    相关产品与服务
    云开发 CloudBase
    云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    http://www.vxiaotou.com