# Компонент MultiLevelMenu - Полная документация ## Назначение компонента `MultiLevelMenu` - универсальный компонент для создания многоуровневых навигационных меню с поддержкой вложенности, различных тем, адаптивным дизайном и расширенной функциональностью. Компонент автоматически обрабатывает иерархическую структуру данных и предоставляет интуитивную навигацию. ## git репозитарий https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ImageSlider/ ## Импорт и регистрация ```coffee # В основном файле приложения (app/temp.coffee) components: 'multilevelmenu': require 'app/shared/MultiLevelMenu' ``` ## Базовое использование ### Минимальная конфигурация ```pug multilevelmenu(:menuItems="menuData") ``` ### С кастомными настройками ```pug multilevelmenu( :menuItems="navigationData" theme="dark" orientation="horizontal" :showIcons="true" :autoClose="true" ) ``` ## Полный список props ### `menuItems` (обязательный) - **Тип:** `Array` - **Описание:** Массив объектов пунктов меню - **Структура объекта:** ```coffee { id: String # Уникальный идентификатор title: String | Array # Заголовок пункта (поддерживает мультиязычные массивы) url: String # Ссылка или маршрут icon: String # Иконка (название или путь) children: Array # Вложенные пункты меню type: String # Тип пункта ('link', 'button', 'divider') disabled: Boolean # Отключенное состояние visible: Boolean # Видимость пункта target: String # Целевое окно для ссылок permissions: Array # Права доступа badge: String | Number # Бейдж/уведомление badgeColor: String # Цвет бейджа } ``` ### `theme` (опциональный) - **Тип:** `String` - **По умолчанию:** `'light'` - **Допустимые значения:** `'light'`, `'dark'`, `'primary'`, `'custom'` - **Описание:** Цветовая тема меню ### `orientation` (опциональный) - **Тип:** `String` - **По умолчанию:** `'horizontal'` - **Допустимые значения:** `'horizontal'`, `'vertical'` - **Описание:** Ориентация меню ### `showIcons` (опциональный) - **Тип:** `Boolean` - **По умолчанию:** `true` - **Описание:** Показывать иконки пунктов меню ### `autoClose` (опциональный) - **Тип:** `Boolean` - **По умолчанию:** `true` - **Описание:** Автоматически закрывать выпадающие меню при клике вне области ### `maxDepth` (опциональный) - **Тип:** `Number` - **По умолчанию:** `3` - **Описание:** Максимальная глубина вложенности меню ### `activeItem` (опциональный) - **Тип:** `String` - **По умолчанию:** `null` - **Описание:** ID активного пункта меню ### `mobileBreakpoint` (опциональный) - **Тип:** `Number` - **По умолчанию:** `768` - **Описание:** Breakpoint для мобильной версии (в px) ### `animationType` (опциональный) - **Тип:** `String` - **По умолчанию:** `'fade'` - **Допустимые значения:** `'fade'`, `'slide'`, `'scale'`, `'none'` - **Описание:** Тип анимации выпадающих меню ## События (Events) ### `@item-click` - **Описание:** Событие клика по пункту меню - **Payload:** ```coffee { item: Object, # Объект пункта меню event: Event, # Нативное событие level: Number, # Уровень вложенности path: Array # Путь от корня } ``` ### `@item-hover` - **Описание:** Событие наведения на пункт меню - **Payload:** Аналогично `item-click` ### `@menu-open` - **Описание:** Событие открытия подменю - **Payload:** ```coffee { item: Object, # Родительский пункт level: Number, # Уровень items: Array # Дочерние пункты } ``` ### `@menu-close` - **Описание:** Событие закрытия подменю - **Payload:** Аналогично `menu-open` ### `@active-change` - **Описание:** Событие изменения активного пункта - **Payload:** ```coffee { oldItem: Object, # Предыдущий активный пункт newItem: Object, # Новый активный пункт level: Number # Уровень изменения } ``` ## Слоты (Slots) ### `[item-content]` (кастомизация содержимого пункта) - **Props:** ```coffee { item: Object, # Объект пункта меню level: Number, # Уровень вложенности isActive: Boolean, # Активное состояние hasChildren: Boolean # Наличие дочерних элементов } ``` - **Пример:** ```pug multilevelmenu(:menuItems="menuData") template([item-content]="{ item, level, isActive }") div(class="flex items-center space-x-3") icon(:name="item.icon" class="w-5 h-5") span {{ item.title }} badge(v-if="item.badge" :count="item.badge") ``` ### `[item-icon]` (кастомизация иконки) - **Props:** Аналогично `item-content` - **Пример:** ```pug multilevelmenu(:menuItems="menuData") template([item-icon]="{ item }") custom-icon(:name="item.icon") ``` ### `[item-badge]` (кастомизация бейджа) - **Props:** Аналогично `item-content` - **Пример:** ```pug multilevelmenu(:menuItems="menuData") template([item-badge]="{ item }") div(class="bg-red-500 text-white rounded-full px-2 py-1 text-xs") {{ item.badge }} ``` ### `[before-menu]` (контент перед меню) - **Пример:** ```pug multilevelmenu(:menuItems="menuData") template([before-menu]) div(class="p-4 border-b") p Добро пожаловать! ``` ### `[after-menu]` (контент после меню) - **Пример:** ```pug multilevelmenu(:menuItems="menuData") template([after-menu]) div(class="p-4 border-t") app-link(to="/help") Помощь ``` ## Методы компонента ### `openSubmenu(itemId)` - **Описание:** Программное открытие подменю - **Параметры:** `itemId` - ID пункта меню - **Пример:** ```coffee @$refs.menu.openSubmenu('events') ``` ### `closeSubmenu(itemId)` - **Описание:** Программное закрытие подменю - **Параметры:** `itemId` - ID пункта меню - **Пример:** ```coffee @$refs.menu.closeSubmenu('events') ``` ### `closeAll()` - **Описание:** Закрыть все открытые подменю - **Пример:** ```coffee @$refs.menu.closeAll() ``` ### `setActive(itemId)` - **Описание:** Установить активный пункт меню - **Параметры:** `itemId` - ID пункта меню - **Пример:** ```coffee @$refs.menu.setActive('current-page') ``` ### `updateMenu(newItems)` - **Описание:** Обновить данные меню - **Параметры:** `newItems` - новый массив пунктов меню - **Пример:** ```coffee @$refs.menu.updateMenu(updatedMenuData) ``` ### `getActiveItem()` - **Описание:** Получить текущий активный пункт - **Возвращает:** Объект активного пункта меню - **Пример:** ```coffee activeItem = @$refs.menu.getActiveItem() ``` ### `getMenuPath(itemId)` - **Описание:** Получить путь к пункту меню - **Параметры:** `itemId` - ID пункта меню - **Возвращает:** Массив ID от корня до пункта - **Пример:** ```coffee path = @$refs.menu.getMenuPath('deep-item') ``` ## Примеры использования в различных сценариях ### 1. Основная навигация сайта ```pug multilevelmenu( :menuItems="mainNavigation" theme="light" orientation="horizontal" :showIcons="false" @item-click="handleNavClick" ) ``` ### 2. Боковое меню администратора ```pug multilevelmenu( :menuItems="adminMenu" theme="dark" orientation="vertical" :maxDepth="4" :activeItem="currentAdminSection" @active-change="onAdminSectionChange" ) ``` ### 3. Мобильное меню с кастомизацией ```pug multilevelmenu( :menuItems="mobileMenu" theme="primary" orientation="vertical" :mobileBreakpoint="1024" :animationType="slide" ) template([item-content]="{ item, level }") div(class="flex items-center justify-between py-3") div(class="flex items-center space-x-4") icon(:name="item.icon" class="w-6 h-6") span(class="text-lg") {{ item.title }} icon( v-if="item.children" name="chevron-right" class="w-4 h-4 transform transition-transform" :class="{ 'rotate-90': isOpen }" ) ``` ### 4. Меню с правами доступа ```pug multilevelmenu( :menuItems="filteredMenu" @item-click="checkPermissions" ) ``` ### 5. Мега-меню с различными типами контента ```pug multilevelmenu(:menuItems="megaMenuData") template([item-content]="{ item, level }") div(v-if="level === 1 && item.type === 'mega'") div(class="grid grid-cols-3 gap-8 p-6") div(v-for="section in item.sections") h4(class="font-semibold mb-3") {{ section.title }} div(class="space-y-2") app-link( v-for="link in section.links" :to="link.url" class="block text-gray-600 hover:text-blue-600" ) {{ link.title }} ``` ## Структура данных меню ### Базовый пример ```coffee menuData = [ { id: 'home' title: ['Главная', 'Home', 'Асосӣ'] url: '/' icon: 'home' visible: true } { id: 'events' title: ['Мероприятия', 'Events', 'Чорабиниҳо'] url: '/events' icon: 'calendar' children: [ { id: 'concerts' title: ['Концерты', 'Concerts', 'Консертҳо'] url: '/events/concerts' icon: 'music' } { id: 'exhibitions' title: ['Выставки', 'Exhibitions', 'Намоишҳо'] url: '/events/exhibitions' icon: 'palette' } ] } { id: 'blog' title: ['Блог', 'Blog', 'Блог'] url: '/blog' icon: 'news' badge: 5 badgeColor: 'red' } { type: 'divider' } { id: 'contacts' title: ['Контакты', 'Contacts', 'Тамос'] url: '/contacts' icon: 'phone' disabled: false } ] ``` ### Расширенная структура с пермишенами ```coffee advancedMenu = [ { id: 'dashboard' title: 'Дашборд' url: '/admin' icon: 'dashboard' permissions: ['admin', 'moderator'] children: [ { id: 'users' title: 'Пользователи' url: '/admin/users' permissions: ['admin'] } { id: 'content' title: 'Контент' url: '/admin/content' permissions: ['admin', 'editor'] } ] } ] ``` ## Темы и стилизация ### Встроенные темы - **light** - светлая тема с белым фоном - **dark** - темная тема с серым фоном - **primary** - тема с основным цветом бренда - **custom** - для полной кастомизации через CSS ### Кастомизация через CSS переменные ```styl .multilevel-menu --menu-bg: theme('colors.white') --menu-text: theme('colors.gray.800') --menu-hover-bg: theme('colors.gray.100') --menu-active-bg: theme('colors.blue.500') --menu-active-text: theme('colors.white') --menu-border: theme('colors.gray.200') --menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1) ``` ### Кастомизация через классы ```pug multilevelmenu( :menuItems="menuData" class="custom-menu" ) ``` ```styl .custom-menu .menu-item @apply px-6 py-3 border-l-4 border-transparent &.active @apply border-blue-500 bg-blue-50 &:hover @apply bg-gray-50 ``` ## Адаптивность и мобильная версия ### Автоматическая адаптация - Горизонтальное меню на десктопе - Вертикальное выдвижное меню на мобильных - Настраиваемый breakpoint - Touch-оптимизированные взаимодействия ### Кастомизация мобильной версии ```pug multilevelmenu( :menuItems="menuData" :mobileBreakpoint="1024" mobileHeader="Навигация" :showMobileHeader="true" ) ``` ## Интеграция с системой прав доступа ### Фильтрация меню по правам ```coffee computed: filteredMenu: -> userPermissions = @$store.state.user.permissions return @filterMenuByPermissions(@menuData, userPermissions) methods: filterMenuByPermissions: (menuItems, permissions) -> return menuItems.filter (item) => if item.permissions return item.permissions.some (perm) -> permissions.includes(perm) return true ``` ## Best Practices ### 1. Оптимизация структуры данных ```coffee # Правильно - плоская структура с ссылками на детей menuData = [ { id: 'parent', title: 'Родитель', url: '/parent' }, { id: 'child', title: 'Ребенок', url: '/child', parentId: 'parent' } ] # Неправильно - глубоко вложенные объекты menuData = [ { title: 'Родитель', children: [ { title: 'Ребенок', children: [...] } ] } ] ``` ### 2. Использование мультиязычных массивов ```coffee menuItem = title: ['Русский текст', 'English text', 'Тоҷикӣ матн'] # Компонент автоматически выберет нужный язык ``` ### 3. Правильная обработка событий ```coffee methods: handleMenuClick: ({ item, event, level }) -> # Предотвращаем переход для специальных пунктов if item.type is 'button' event.preventDefault() @handleButtonAction(item) # Логируем навигацию analytics.track('menu_click', { item: item.id, level: level }) ``` ### 4. Оптимизация производительности ```pug multilevelmenu(:menuItems="menuData" :key="menuVersion") multilevelmenu(:menuItems="dynamicMenu") ``` ## Отладка и разработка ### Включение режима отладки ```pug multilevelmenu( :menuItems="menuData" debug @item-click="console.log" @menu-open="console.log" ) ``` ### Проверка состояния меню ```coffee # В консоли разработчика $refs.menu.getActiveItem() $refs.menu.getMenuPath('item-id') ``` Компонент MultiLevelMenu предоставляет мощный и гибкий инструмент для создания сложных навигационных систем с поддержкой многоуровневой структуры, адаптивным дизайном и расширенными возможностями кастомизации.