Menu

Компонент Menu в библиотеке Element Plus предназначен для построения навигационных меню с поддержкой вложенных пунктов, вертикальной или горизонтальной ориентации и гибкой кастомизации внешнего вида. Он тесно интегрирован с системой маршрутизации Vue и позволяет создавать как простые списки ссылок, так и сложные многоуровневые меню с подменю.

Основная структура Menu строится с использованием элементов: el-menu, el-menu-item и el-sub-menu.

Пример базовой структуры:

<template>
  <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal">
    <el-menu-item index="1">Главная</el-menu-item>
    <el-sub-menu index="2">
      <template #title>Продукты</template>
      <el-menu-item index="2-1">Продукт A</el-menu-item>
      <el-menu-item index="2-2">Продукт B</el-menu-item>
    </el-sub-menu>
    <el-menu-item index="3">Контакты</el-menu-item>
  </el-menu>
</template>

<script setup>
import { ref } from 'vue'

const activeIndex = ref('1')
</script>

Ключевые моменты:

  • el-menu поддерживает два режима: vertical (по умолчанию) и horizontal.
  • default-active задаёт активный пункт меню при первой загрузке.
  • el-sub-menu используется для создания вложенных пунктов. Заголовок подменю определяется через слот #title.

Свойства и конфигурация

el-menu поддерживает множество полезных свойств:

  • mode — ориентация меню (vertical, horizontal, inline).
  • default-active — индекс активного пункта.
  • unique-opened — если установлено в true, разрешает открывать только одно подменю одновременно.
  • collapse — сворачивает меню в компактный вид, часто используется вместе с боковыми панелями.
  • background-color — цвет фона меню.
  • text-color и active-text-color — цвет текста пунктов и активного элемента соответственно.

el-menu-item имеет ключевое свойство:

  • index — уникальный идентификатор пункта меню, используемый для управления активностью и событиями.

el-sub-menu расширяет функциональность:

  • index — уникальный идентификатор подменю.
  • disabled — блокирует доступ к подменю.
  • Поддерживает слот #title для кастомного заголовка.

Работа с событиями

Menu предоставляет несколько событий для интерактивного управления:

  • select — срабатывает при выборе пункта меню, передаёт index выбранного элемента.
  • open — вызывается при открытии подменю.
  • close — вызывается при закрытии подменю.

Пример обработки событий:

<el-menu
  :default-active="activeIndex"
  @select="handleSelect"
  @open="handleOpen"
  @close="handleClose"
>
  <el-menu-item index="1">Главная</el-menu-item>
  <el-sub-menu index="2">
    <template #title>Продукты</template>
    <el-menu-item index="2-1">Продукт A</el-menu-item>
    <el-menu-item index="2-2">Продукт B</el-menu-item>
  </el-sub-menu>
</el-menu>

<script setup>
import { ref } from 'vue'

const activeIndex = ref('1')

function handleSelect(index) {
  console.log('Выбран пункт:', index)
}

function handleOpen(index) {
  console.log('Открыто подменю:', index)
}

function handleClose(index) {
  console.log('Закрыто подменю:', index)
}
</script>

Свёртывание меню и режим «collapsed»

Для создания боковых панелей с компактным меню используется свойство collapse:

<el-menu
  :collapse="isCollapsed"
  :default-active="activeIndex"
  class="el-menu-vertical-demo"
>
  <el-menu-item index="1">Главная</el-menu-item>
  <el-sub-menu index="2">
    <template #title>Продукты</template>
    <el-menu-item index="2-1">Продукт A</el-menu-item>
  </el-sub-menu>
</el-menu>

<script setup>
import { ref } from 'vue'

const activeIndex = ref('1')
const isCollapsed = ref(false)
</script>
  • При collapse=true меню сворачивается, показывая только иконки, если они заданы через слот #title или атрибут icon.
  • Можно динамически управлять сворачиванием с помощью реактивного состояния.

Горизонтальное меню и интеграция с роутером

Горизонтальное меню идеально подходит для шапки сайта:

<el-menu mode="horizontal" :default-active="activeIndex">
  <el-menu-item index="1" @click="goHome">Главная</el-menu-item>
  <el-menu-item index="2" @click="goProducts">Продукты</el-menu-item>
</el-menu>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()
const activeIndex = ref('1')

function goHome() {
  router.push({ name: 'Home' })
}

function goProducts() {
  router.push({ name: 'Products' })
}
</script>
  • Каждый пункт меню может быть связан с маршрутом Vue, обеспечивая SPA-навигацию.
  • Свойство index удобно использовать для синхронизации с default-active, чтобы выделять текущую страницу.

Кастомизация и стили

Menu в Element Plus легко кастомизируется через CSS-переменные и классы:

  • .el-menu — контейнер меню.
  • .el-menu-item — отдельный пункт меню.
  • .el-sub-menu__title — заголовок подменю.
  • Переменные для цветов и размеров позволяют создавать светлые, тёмные или фирменные темы.

Пример настройки цветов:

<el-menu
  background-color="#001529"
  text-color="#fff"
  active-text-color="#409EFF"
  :default-active="activeIndex"
>
  <el-menu-item index="1">Главная</el-menu-item>
  <el-menu-item index="2">Продукты</el-menu-item>
</el-menu>
  • background-color — фон всего меню.
  • text-color — цвет текста пунктов.
  • active-text-color — выделение активного пункта.

Динамическое создание меню

Меню можно строить на основе массива данных, что упрощает работу с большим количеством пунктов:

<template>
  <el-menu :default-active="activeIndex">
    <template v-for="item in menuData">
      <el-menu-item v-if="!item.children" :key="item.index" :index="item.index">
        {{ item.label }}
      </el-menu-item>
      <el-sub-menu v-else :key="item.index" :index="item.index">
        <template #title>{{ item.label }}</template>
        <el-menu-item v-for="child in item.children" :key="child.index" :index="child.index">
          {{ child.label }}
        </el-menu-item>
      </el-sub-menu>
    </template>
  </el-menu>
</template>

<script setup>
import { ref } from 'vue'

const activeIndex = ref('1')
const menuData = [
  { index: '1', label: 'Главная' },
  { index: '2', label: 'Продукты', children: [
    { index: '2-1', label: 'Продукт A' },
    { index: '2-2', label: 'Продукт B' },
  ]},
  { index: '3', label: 'Контакты' }
]
</script>
  • Позволяет легко расширять меню без ручного добавления компонентов.
  • Поддерживает вложенность на несколько уровней с помощью рекурсии.

Использование иконок в меню

Для улучшения визуального восприятия часто используют иконки. В Element Plus для этого применяется слот #title или атрибут icon:

<el-menu :default-active="activeIndex">
  <el-menu-item index="1">
    <template #title>
      <el-icon><HomeFilled /></el-icon>
      Главная
    </template>
  </el-menu-item>
  <el-sub-menu index="2">
    <template #title>
      <el-icon><Menu /></el-icon>
      Продукты
    </template>
    <el-menu-item index="2-1">Продукт A</el-menu-item>
  </el-sub-menu>
</el-menu>

<script setup>
import { ref } from 'vue'
import { HomeFilled, Menu } from '@element-plus/icons-vue'

const activeIndex = ref('1')
</script>
  • Слот #title позволяет полностью кастомизировать заголовок пункта меню.
  • Иконки могут быть любыми компонентами, поддерживаемыми Vue 3.

Эти возможности делают Menu в Element Plus гибким инструментом для создания навигации любого уровня сложности, от простых горизонтальных шапок до многоуровневых боковых панелей с динамическим содержимым.