Вложенные меню

В библиотеке Naive UI меню представлено через компонент n-menu, который позволяет строить как простые списки навигации, так и сложные иерархические структуры. Вложенные меню реализуются с помощью свойства children, позволяющего определить дочерние элементы для каждого пункта меню.

import { NMenu } from 'naive-ui'

const menuOptions = [
  {
    label: 'Файл',
    key: 'file',
    children: [
      { label: 'Создать', key: 'create' },
      { label: 'Открыть', key: 'open' },
      { 
        label: 'Экспорт',
        key: 'export',
        children: [
          { label: 'PDF', key: 'export_pdf' },
          { label: 'Excel', key: 'export_excel' }
        ]
      }
    ]
  },
  { label: 'Правка', key: 'edit' },
  { label: 'Вид', key: 'view' }
]

<NMenu :options="menuOptions" />

В этом примере меню Файл имеет три дочерних пункта, один из которых (Экспорт) содержит своё подменю. Такой подход позволяет строить меню произвольной глубины без необходимости создавать отдельные компоненты для каждого уровня вложенности.

Настройка поведения вложенных меню

Naive UI предоставляет гибкие настройки для вложенных пунктов:

  • show-arrow: отображение стрелки у элементов с дочерними пунктами.
  • collapsed: возможность сворачивания всего меню или отдельных веток.
  • value: текущий выбранный пункт, синхронизируемый с v-model.
<NMenu
  :options="menuOptions"
  :collapsed="false"
  :show-arrow="true"
  v-model:value="activeKey"
/>

Использование свойства show-arrow делает вложенные пункты более наглядными, показывая пользователю, что элемент имеет подменю.

Динамическое формирование меню

Меню в Naive UI можно строить динамически, что особенно важно для приложений с большим количеством пунктов или когда структура меню зависит от данных с сервера.

import { ref } from 'vue'

const menuOptions = ref([])

fetch('/api/menu')
  .then(res => res.json())
  .then(data => {
    menuOptions.value = data.map(item => ({
      label: item.name,
      key: item.id,
      children: item.children?.map(sub => ({
        label: sub.name,
        key: sub.id
      }))
    }))
  })

Такой подход позволяет автоматически создавать вложенные меню любого уровня, основываясь на JSON-структуре данных, получаемых с сервера.

Стилизация вложенных меню

Для настройки внешнего вида вложенных пунктов используется комбинация CSS-переменных и классов Naive UI:

  • --n-menu-item-padding-left позволяет увеличивать отступ для вложенных элементов, создавая визуальную иерархию.
  • n-menu-item--child и n-menu-item--group дают возможность таргетировать отдельные уровни меню в стилях.
.n-menu-item--child {
  padding-left: 20px;
}

.n-menu-item--group {
  font-weight: bold;
}

Такой подход обеспечивает чёткое разделение уровней меню и улучшает читаемость интерфейса при глубокой вложенности.

Управление событиями

Naive UI предоставляет возможность обрабатывать события выбора пунктов, включая вложенные:

  • on-update:value: срабатывает при выборе любого пункта меню.
  • on-open-change: отслеживает открытие и закрытие вложенных подменю.
<NMenu
  :options="menuOptions"
  v-model:value="activeKey"
  @update:value="handleSelect"
  @open-change="handleOpenChange"
/>

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

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

Это позволяет реализовать динамическую загрузку содержимого подменю, ведение истории навигации или интеграцию с роутером.

Интеграция с маршрутизацией Vue Router

Вложенные меню легко связываются с маршрутизацией. Вместо ключей key можно использовать to, аналогично свойству router-link:

const menuOptions = [
  {
    label: 'Документы',
    key: 'docs',
    children: [
      { label: 'Отчёты', key: 'reports', to: '/docs/reports' },
      { label: 'Шаблоны', key: 'templates', to: '/docs/templates' }
    ]
  }
]

Naive UI автоматически использует Vue Router для навигации при клике на пункт с to, что делает вложенные меню полностью совместимыми с SPA.

Продвинутые техники

  • Lazy Loading вложенных пунктов: можно создавать подменю только при открытии родительского пункта, загружая данные с сервера по событию on-open-change.
  • Группировка пунктов: свойства group и group-label позволяют логически объединять элементы меню внутри одного уровня.
  • Иконки для вложенных пунктов: с помощью свойства icon можно визуально различать типы подменю и повышать юзабилити.
{
  label: 'Настройки',
  key: 'settings',
  icon: 'SettingOutlined',
  children: [
    { label: 'Профиль', key: 'profile', icon: 'UserOutlined' },
    { label: 'Безопасность', key: 'security', icon: 'LockOutlined' }
  ]
}

Такой подход позволяет строить богатые и наглядные интерфейсы с глубокими иерархиями, оставаясь в рамках одного компонента n-menu.


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