返回

解析 PC 项目实战(一):el-menu 构建多层级树状菜单,简单易懂!

前端

前言

树状菜单是一种常见的 UI 组件,它可以将数据结构化地组织成一棵树状结构,方便用户浏览和选择。在本文中,我们将探讨如何使用 Vue.js 的 el-menu 组件构建一个多层级的树状菜单。

需求说明

我们希望实现一个动态渲染的树状菜单,其中菜单项可以根据后端返回的嵌套数据进行更新。菜单分为两种类型:

  • 菜单: 不可点击,只能下拉打开子菜单。
  • 功能: 可以点击,执行特定操作。

菜单类型由 menuType 字段区分。

需求实现

封装子菜单组

首先,我们需要封装一个子菜单组组件,它将负责渲染菜单项及其子菜单。

<template>
  <el-menu-item :index="index" :class="{'is-active': isActive}">
    <template v-if="menu.children">
      <span slot="title">{{ menu.label }}</span>
      <el-menu v-bind="$attrs" :default-active="activeName">
        <sub-menu v-for="subMenu in menu.children" :key="subMenu.index" :menu="subMenu" :index="subMenu.index" />
      </el-menu>
    </template>
    <template v-else>
      <el-menu-item :index="index" :class="{'is-active': isActive}">{{ menu.label }}</el-menu-item>
    </template>
  </el-menu-item>
</template>

<script>
export default {
  props: ['menu', 'index', 'activeName'],
  data() {
    return {
      isActive: false
    }
  },
  methods: {
    handleOpen() {
      this.isActive = true
    },
    handleClose() {
      this.isActive = false
    }
  }
}
</script>

在子菜单组中,我们使用递归的方式来渲染子菜单。当菜单项具有子菜单时,我们渲染一个 el-menu 组件并将其传递给子菜单组。当菜单项没有子菜单时,我们直接渲染一个 el-menu-item。

菜单渲染

接下来,我们需要在父组件中渲染菜单。

<template>
  <el-menu v-model="activeName" @open="handleOpen" @close="handleClose">
    <sub-menu v-for="menu in menuData" :key="menu.index" :menu="menu" :index="menu.index" />
  </el-menu>
</template>

<script>
import SubMenu from './SubMenu.vue'

export default {
  components: { SubMenu },
  data() {
    return {
      menuData: [
        {
          index: 0,
          label: '菜单 1',
          children: [
            { index: 1, label: '子菜单 1' },
            { index: 2, label: '子菜单 2' }
          ]
        },
        {
          index: 1,
          label: '功能 2',
          menuType: 'function'
        }
      ],
      activeName: ''
    }
  },
  methods: {
    handleOpen(name) {
      this.activeName = name
    },
    handleClose() {
      this.activeName = ''
    }
  }
}
</script>

在父组件中,我们使用 v-model 来控制菜单的选中状态,并监听 open 和 close 事件。当菜单项被打开或关闭时,我们相应地更新 activeName。

总结

通过上述步骤,我们成功构建了一个多层级的树状菜单,它可以根据后端返回的嵌套数据进行动态渲染。菜单类型由 menuType 字段区分,并支持可点击的功能菜单项。