|
|
3 hafta önce | |
|---|---|---|
| .. | ||
| README.md | 3 hafta önce | |
| index.coffee | 3 hafta önce | |
| index.pug | 3 hafta önce | |
| index.styl | 3 hafta önce | |
MultiLevelMenu - универсальный компонент для создания многоуровневых навигационных меню с поддержкой вложенности, различных тем, адаптивным дизайном и расширенной функциональностью. Компонент автоматически обрабатывает иерархическую структуру данных и предоставляет интуитивную навигацию.
https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/ImageSlider/
# В основном файле приложения (app/temp.coffee)
components:
'multilevelmenu': require 'app/shared/MultiLevelMenu'
multilevelmenu(:menuItems="menuData")
multilevelmenu(
:menuItems="navigationData"
theme="dark"
orientation="horizontal"
:showIcons="true"
:autoClose="true"
)
menuItems (обязательный)ArrayСтруктура объекта:
{
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 (опциональный)BooleantrueautoClose (опциональный)BooleantruemaxDepth (опциональный)Number3activeItem (опциональный)StringnullmobileBreakpoint (опциональный)Number768animationType (опциональный)String'fade''fade', 'slide', 'scale', 'none'@item-clickPayload:
{
item: Object, # Объект пункта меню
event: Event, # Нативное событие
level: Number, # Уровень вложенности
path: Array # Путь от корня
}
@item-hoveritem-click@menu-openPayload:
{
item: Object, # Родительский пункт
level: Number, # Уровень
items: Array # Дочерние пункты
}
@menu-closemenu-open@active-changePayload:
{
oldItem: Object, # Предыдущий активный пункт
newItem: Object, # Новый активный пункт
level: Number # Уровень изменения
}
[item-content] (кастомизация содержимого пункта)Props:
{
item: Object, # Объект пункта меню
level: Number, # Уровень вложенности
isActive: Boolean, # Активное состояние
hasChildren: Boolean # Наличие дочерних элементов
}
Пример:
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] (кастомизация иконки)item-contentПример:
multilevelmenu(:menuItems="menuData")
template([item-icon]="{ item }")
custom-icon(:name="item.icon")
[item-badge] (кастомизация бейджа)item-contentПример:
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] (контент перед меню)Пример:
multilevelmenu(:menuItems="menuData")
template([before-menu])
div(class="p-4 border-b")
p Добро пожаловать!
[after-menu] (контент после меню)Пример:
multilevelmenu(:menuItems="menuData")
template([after-menu])
div(class="p-4 border-t")
app-link(to="/help") Помощь
openSubmenu(itemId)itemId - ID пункта менюПример:
@$refs.menu.openSubmenu('events')
closeSubmenu(itemId)itemId - ID пункта менюПример:
@$refs.menu.closeSubmenu('events')
closeAll()Пример:
@$refs.menu.closeAll()
setActive(itemId)itemId - ID пункта менюПример:
@$refs.menu.setActive('current-page')
updateMenu(newItems)newItems - новый массив пунктов менюПример:
@$refs.menu.updateMenu(updatedMenuData)
getActiveItem()Пример:
activeItem = @$refs.menu.getActiveItem()
getMenuPath(itemId)itemId - ID пункта менюПример:
path = @$refs.menu.getMenuPath('deep-item')
multilevelmenu(
:menuItems="mainNavigation"
theme="light"
orientation="horizontal"
:showIcons="false"
@item-click="handleNavClick"
)
multilevelmenu(
:menuItems="adminMenu"
theme="dark"
orientation="vertical"
:maxDepth="4"
:activeItem="currentAdminSection"
@active-change="onAdminSectionChange"
)
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 }"
)
multilevelmenu(
:menuItems="filteredMenu"
@item-click="checkPermissions"
)
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 }}
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
}
]
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']
}
]
}
]
.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)
multilevelmenu(
:menuItems="menuData"
class="custom-menu"
)
.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
multilevelmenu(
:menuItems="menuData"
:mobileBreakpoint="1024"
mobileHeader="Навигация"
:showMobileHeader="true"
)
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
# Правильно - плоская структура с ссылками на детей
menuData = [
{ id: 'parent', title: 'Родитель', url: '/parent' },
{ id: 'child', title: 'Ребенок', url: '/child', parentId: 'parent' }
]
# Неправильно - глубоко вложенные объекты
menuData = [
{
title: 'Родитель',
children: [
{ title: 'Ребенок', children: [...] }
]
}
]
menuItem =
title: ['Русский текст', 'English text', 'Тоҷикӣ матн']
# Компонент автоматически выберет нужный язык
methods:
handleMenuClick: ({ item, event, level }) ->
# Предотвращаем переход для специальных пунктов
if item.type is 'button'
event.preventDefault()
@handleButtonAction(item)
# Логируем навигацию
analytics.track('menu_click', {
item: item.id,
level: level
})
<!-- Правильно - стабильные ID -->
multilevelmenu(:menuItems="menuData" :key="menuVersion")
<!-- Неправильно - изменяемые ID -->
multilevelmenu(:menuItems="dynamicMenu")
multilevelmenu(
:menuItems="menuData"
debug
@item-click="console.log"
@menu-open="console.log"
)
# В консоли разработчика
$refs.menu.getActiveItem()
$refs.menu.getMenuPath('item-id')
Компонент MultiLevelMenu предоставляет мощный и гибкий инструмент для создания сложных навигационных систем с поддержкой многоуровневой структуры, адаптивным дизайном и расширенными возможностями кастомизации.