|
|
@@ -0,0 +1,432 @@
|
|
|
+# Компонент AppLink - Полная документация
|
|
|
+
|
|
|
+## Назначение компонента
|
|
|
+
|
|
|
+`AppLink` - универсальный компонент для работы со ссылками в приложении. Автоматически определяет тип ссылки (внутренняя/внешняя) и использует соответствующий компонент (`router-link` для внутренних маршрутов, `a` для внешних URL). Обеспечивает единообразие поведения, безопасности и стилизации всех ссылок в приложении.
|
|
|
+
|
|
|
+## Импорт и регистрация
|
|
|
+
|
|
|
+```coffee
|
|
|
+# В основном файле приложения (app/temp.coffee)
|
|
|
+components:
|
|
|
+ 'app-link': require 'app/shared/AppLink'
|
|
|
+```
|
|
|
+
|
|
|
+## Базовое использование
|
|
|
+
|
|
|
+### 1. Простая внутренняя ссылка
|
|
|
+```pug
|
|
|
+app-link(to="/about") О нас
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Внешняя ссылка
|
|
|
+```pug
|
|
|
+app-link(to="https://example.com") Внешний сайт
|
|
|
+```
|
|
|
+
|
|
|
+## Полный список props
|
|
|
+
|
|
|
+### `to` (обязательный)
|
|
|
+- **Тип:** `String | Object`
|
|
|
+- **Описание:** Назначение ссылки
|
|
|
+- **Примеры:**
|
|
|
+ ```pug
|
|
|
+ //- Строковый путь
|
|
|
+ app-link(to="/events")
|
|
|
+
|
|
|
+ //- Объект маршрута Vue Router
|
|
|
+ app-link(:to="{ name: 'EventDetail', params: { id: event._id } }")
|
|
|
+
|
|
|
+ //- Внешний URL
|
|
|
+ app-link(to="https://facebook.com/borbad")
|
|
|
+
|
|
|
+ //- Email ссылка
|
|
|
+ app-link(to="mailto:info@borbad.s5l.ru")
|
|
|
+
|
|
|
+ //- Телефонная ссылка
|
|
|
+ app-link(to="tel:+992371234567")
|
|
|
+ ```
|
|
|
+
|
|
|
+### `href` (опциональный)
|
|
|
+- **Тип:** `String`
|
|
|
+- **По умолчанию:** `''`
|
|
|
+- **Описание:** Альтернативный способ указания внешнего URL
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(href="https://example.com" to="/fallback") Ссылка
|
|
|
+ ```
|
|
|
+
|
|
|
+### `target` (опциональный)
|
|
|
+- **Тип:** `String`
|
|
|
+- **По умолчанию:** `'_self'`
|
|
|
+- **Допустимые значения:** `'_self'`, `'_blank'`, `'_parent'`, `'_top'`
|
|
|
+- **Описание:** Целевое окно для ссылки
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(to="https://example.com" target="_blank") Открыть в новом окне
|
|
|
+ ```
|
|
|
+
|
|
|
+### `rel` (опциональный)
|
|
|
+- **Тип:** `String`
|
|
|
+- **По умолчанию:** `''`
|
|
|
+- **Описание:** Атрибут rel для внешних ссылок
|
|
|
+- **Примечание:** Для `target="_blank"` автоматически добавляется `noopener noreferrer`
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(to="https://example.com" rel="nofollow") Ссылка nofollow
|
|
|
+ ```
|
|
|
+
|
|
|
+### `class` (опциональный)
|
|
|
+- **Тип:** `String | Object | Array`
|
|
|
+- **По умолчанию:** `''`
|
|
|
+- **Описание:** CSS классы для стилизации
|
|
|
+- **Примеры:**
|
|
|
+ ```pug
|
|
|
+ //- Строка
|
|
|
+ app-link(to="/" class="text-blue-600 hover:text-blue-800")
|
|
|
+
|
|
|
+ //- Объект
|
|
|
+ app-link(to="/" :class="{ 'font-bold': isActive }")
|
|
|
+
|
|
|
+ //- Массив
|
|
|
+ app-link(to="/" :class="['text-blue-600', 'hover:text-blue-800']")
|
|
|
+ ```
|
|
|
+
|
|
|
+### `activeClass` (опциональный)
|
|
|
+- **Тип:** `String`
|
|
|
+- **По умолчанию:** `'app-link--active'`
|
|
|
+- **Описание:** CSS класс для активного состояния (только для внутренних ссылок)
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(to="/events" active-class="bg-blue-100 text-blue-800")
|
|
|
+ ```
|
|
|
+
|
|
|
+### `exact` (опциональный)
|
|
|
+- **Тип:** `Boolean`
|
|
|
+- **По умолчанию:** `false`
|
|
|
+- **Описание:** Точное совпадение для активного класса
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(to="/" exact) Главная
|
|
|
+ ```
|
|
|
+
|
|
|
+## События (Events)
|
|
|
+
|
|
|
+### `@click`
|
|
|
+- **Описание:** Событие клика по ссылке
|
|
|
+- **Payload:** `Event` объект
|
|
|
+- **Пример:**
|
|
|
+ ```pug
|
|
|
+ app-link(to="/events" @click="handleEventClick")
|
|
|
+ ```
|
|
|
+
|
|
|
+## Слоты (Slots)
|
|
|
+
|
|
|
+### `[body]` (основной слот)
|
|
|
+- **Описание:** Содержимое ссылки
|
|
|
+- **Примеры:**
|
|
|
+ ```pug
|
|
|
+ //- Текстовое содержимое
|
|
|
+ app-link(to="/events") Все мероприятия
|
|
|
+
|
|
|
+ //- HTML содержимое
|
|
|
+ app-link(to="/events")
|
|
|
+ div(class="flex items-center")
|
|
|
+ span Мероприятия
|
|
|
+ icon(name="arrow-right")
|
|
|
+
|
|
|
+ //- Компоненты внутри
|
|
|
+ app-link(to="/cart")
|
|
|
+ cart-icon
|
|
|
+ span Корзина
|
|
|
+ badge(:count="cartCount")
|
|
|
+ ```
|
|
|
+
|
|
|
+## Стили и CSS классы
|
|
|
+
|
|
|
+### Базовые классы
|
|
|
+- `.app-link` - основной класс компонента
|
|
|
+- `.app-link--active` - класс активного состояния (по умолчанию)
|
|
|
+
|
|
|
+### Модификаторы размера
|
|
|
+```pug
|
|
|
+app-link(to="/" class="app-link--sm") Маленькая
|
|
|
+app-link(to="/" class="app-link--md") Средняя
|
|
|
+app-link(to="/" class="app-link--lg") Большая
|
|
|
+```
|
|
|
+
|
|
|
+### Варианты стилей
|
|
|
+```pug
|
|
|
+//- Основной стиль
|
|
|
+app-link(to="/" class="app-link--primary") Основная
|
|
|
+
|
|
|
+//- Вторичный стиль
|
|
|
+app-link(to="/" class="app-link--secondary") Вторичная
|
|
|
+
|
|
|
+//- Текстовый стиль
|
|
|
+app-link(to="/" class="app-link--text") Текстовая
|
|
|
+
|
|
|
+//- С иконкой внешней ссылки
|
|
|
+app-link(to="https://example.com" class="app-link--external") Внешняя
|
|
|
+```
|
|
|
+
|
|
|
+### Утилитарные классы
|
|
|
+```pug
|
|
|
+//- Без подчеркивания
|
|
|
+app-link(to="/" class="no-underline") Без подчеркивания
|
|
|
+
|
|
|
+//- Подчеркивание при hover
|
|
|
+app-link(to="/" class="underline-on-hover") Подчеркивание при наведении
|
|
|
+```
|
|
|
+
|
|
|
+## Примеры использования в различных сценариях
|
|
|
+
|
|
|
+### 1. Навигационное меню
|
|
|
+```pug
|
|
|
+nav(class="flex space-x-6")
|
|
|
+ app-link(
|
|
|
+ to="/"
|
|
|
+ exact
|
|
|
+ active-class="text-blue-600 border-blue-600"
|
|
|
+ class="pb-2 border-b-2 border-transparent transition-colors"
|
|
|
+ ) Главная
|
|
|
+
|
|
|
+ app-link(
|
|
|
+ to="/events"
|
|
|
+ active-class="text-blue-600 border-blue-600"
|
|
|
+ class="pb-2 border-b-2 border-transparent transition-colors"
|
|
|
+ ) Мероприятия
|
|
|
+
|
|
|
+ app-link(
|
|
|
+ to="/blog"
|
|
|
+ active-class="text-blue-600 border-blue-600"
|
|
|
+ class="pb-2 border-b-2 border-transparent transition-colors"
|
|
|
+ ) Блог
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Карточки мероприятий
|
|
|
+```pug
|
|
|
+div(
|
|
|
+ v-for="event in events"
|
|
|
+ :key="event._id"
|
|
|
+ class="bg-white rounded-lg shadow-md overflow-hidden"
|
|
|
+)
|
|
|
+ app-link(:to="'/events/' + event._id")
|
|
|
+ img(:src="event.image" :alt="event.title" class="w-full h-48 object-cover")
|
|
|
+ div(class="p-4")
|
|
|
+ h3(class="text-lg font-semibold mb-2") {{ event.title }}
|
|
|
+ p(class="text-gray-600 mb-2") {{ event.event_data.location }}
|
|
|
+ p(class="text-gray-500 text-sm") {{ formatDate(event.event_data.event_date) }}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. Социальные ссылки
|
|
|
+```pug
|
|
|
+div(class="flex space-x-4")
|
|
|
+ app-link(
|
|
|
+ to="https://facebook.com/borbad"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ class="app-link--external text-gray-600 hover:text-blue-600"
|
|
|
+ )
|
|
|
+ icon(name="facebook" class="w-6 h-6")
|
|
|
+
|
|
|
+ app-link(
|
|
|
+ to="https://instagram.com/borbad"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ class="app-link--external text-gray-600 hover:text-pink-600"
|
|
|
+ )
|
|
|
+ icon(name="instagram" class="w-6 h-6")
|
|
|
+```
|
|
|
+
|
|
|
+### 4. Кнопки действия
|
|
|
+```pug
|
|
|
+div(class="flex space-x-4")
|
|
|
+ app-link(
|
|
|
+ to="/events"
|
|
|
+ class="app-link--primary app-link--lg"
|
|
|
+ ) Смотреть мероприятия
|
|
|
+
|
|
|
+ app-link(
|
|
|
+ to="/contacts"
|
|
|
+ class="app-link--secondary app-link--lg"
|
|
|
+ ) Связаться с нами
|
|
|
+```
|
|
|
+
|
|
|
+### 5. Ссылки с параметрами запроса
|
|
|
+```pug
|
|
|
+app-link(
|
|
|
+ :to="{
|
|
|
+ path: '/events',
|
|
|
+ query: {
|
|
|
+ category: 'music',
|
|
|
+ date: '2024-03'
|
|
|
+ }
|
|
|
+ }"
|
|
|
+ class="text-blue-600 hover:text-blue-800"
|
|
|
+) Музыкальные мероприятия марта
|
|
|
+```
|
|
|
+
|
|
|
+### 6. Ссылки с именованными маршрутами
|
|
|
+```pug
|
|
|
+app-link(
|
|
|
+ :to="{
|
|
|
+ name: 'BlogPost',
|
|
|
+ params: {
|
|
|
+ id: post._id,
|
|
|
+ slug: post.slug
|
|
|
+ }
|
|
|
+ }"
|
|
|
+ class="block p-6 bg-white rounded-lg shadow hover:shadow-md transition-shadow"
|
|
|
+)
|
|
|
+ h3(class="text-xl font-semibold mb-2") {{ post.title }}
|
|
|
+ p(class="text-gray-600") {{ post.excerpt }}
|
|
|
+```
|
|
|
+
|
|
|
+### 7. Email и телефонные ссылки
|
|
|
+```pug
|
|
|
+div(class="space-y-2")
|
|
|
+ app-link(
|
|
|
+ to="mailto:info@borbad.s5l.ru"
|
|
|
+ class="text-blue-600 hover:text-blue-800"
|
|
|
+ ) info@borbad.s5l.ru
|
|
|
+
|
|
|
+ app-link(
|
|
|
+ to="tel:+992371234567"
|
|
|
+ class="text-blue-600 hover:text-blue-800"
|
|
|
+ ) +992 37 123-45-67
|
|
|
+```
|
|
|
+
|
|
|
+## Особенности работы
|
|
|
+
|
|
|
+### Автоматическое определение типа ссылки
|
|
|
+```coffee
|
|
|
+# Внутренние ссылки
|
|
|
+'/about'
|
|
|
+'/events/123'
|
|
|
+{ name: 'Home' }
|
|
|
+{ path: '/blog', query: { category: 'news' } }
|
|
|
+
|
|
|
+# Внешние ссылки
|
|
|
+'https://example.com'
|
|
|
+'//cdn.example.com/image.jpg'
|
|
|
+'mailto:test@example.com'
|
|
|
+'tel:+1234567890'
|
|
|
+'ftp://example.com'
|
|
|
+'#section'
|
|
|
+```
|
|
|
+
|
|
|
+### Безопасность внешних ссылок
|
|
|
+- Автоматическое добавление `rel="noopener noreferrer"` для `target="_blank"`
|
|
|
+- Защита от уязвимостей типа tabnabbing
|
|
|
+- Валидация URL
|
|
|
+
|
|
|
+### Интеграция с аналитикой
|
|
|
+```coffee
|
|
|
+# В обработчиках событий
|
|
|
+handleExternalClick: (event) ->
|
|
|
+ EventBus.emit('external_link_clicked', {
|
|
|
+ url: @normalizedHref
|
|
|
+ target: @target
|
|
|
+ })
|
|
|
+
|
|
|
+handleInternalClick: (event) ->
|
|
|
+ EventBus.emit('internal_link_clicked', {
|
|
|
+ to: @normalizedTo
|
|
|
+ route: @$route
|
|
|
+ })
|
|
|
+```
|
|
|
+
|
|
|
+## Кастомизация
|
|
|
+
|
|
|
+### Создание собственных вариантов стилей
|
|
|
+```styl
|
|
|
+// В глобальных стилях
|
|
|
+.app-link--custom
|
|
|
+ @apply bg-gradient-to-r from-purple-500 to-pink-500 text-white
|
|
|
+
|
|
|
+ &:hover
|
|
|
+ @apply from-purple-600 to-pink-600
|
|
|
+
|
|
|
+ &.app-link--active
|
|
|
+ @apply from-purple-700 to-pink-700
|
|
|
+```
|
|
|
+
|
|
|
+### Расширение функциональности
|
|
|
+```coffee
|
|
|
+# Создание производного компонента
|
|
|
+CustomAppLink =
|
|
|
+ name: 'CustomAppLink'
|
|
|
+ extends: require 'app/shared/AppLink'
|
|
|
+
|
|
|
+ methods:
|
|
|
+ handleExternalClick: (event) ->
|
|
|
+ # Дополнительная логика
|
|
|
+ analytics.track('external_link_click', { url: @normalizedHref })
|
|
|
+
|
|
|
+ # Вызов родительского метода
|
|
|
+ @$super.handleExternalClick(event)
|
|
|
+```
|
|
|
+
|
|
|
+## Отладка и разработка
|
|
|
+
|
|
|
+### Проверка типа ссылки
|
|
|
+```pug
|
|
|
+app-link(
|
|
|
+ :to="linkUrl"
|
|
|
+ :class="{ 'border-green-500': $el.isRouterLink, 'border-red-500': $el.isExternalLink }"
|
|
|
+) Ссылка
|
|
|
+```
|
|
|
+
|
|
|
+### Логирование событий
|
|
|
+```coffee
|
|
|
+# В основном приложении
|
|
|
+EventBus.on 'external_link_clicked', (data) ->
|
|
|
+ debug.log "Внешняя ссылка: "+data.url
|
|
|
+
|
|
|
+EventBus.on 'internal_link_clicked', (data) ->
|
|
|
+ debug.log "Внутренняя ссылка: "+JSON.stringify(data.to)
|
|
|
+```
|
|
|
+
|
|
|
+## Best Practices
|
|
|
+
|
|
|
+### 1. Всегда используйте AppLink вместо прямых тегов
|
|
|
+```pug
|
|
|
+//- Правильно
|
|
|
+app-link(to="/about") О нас
|
|
|
+
|
|
|
+//- Неправильно
|
|
|
+a(href="/about") О нас
|
|
|
+router-link(to="/about") О нас
|
|
|
+```
|
|
|
+
|
|
|
+### 2. Используйте правильные target и rel для внешних ссылок
|
|
|
+```pug
|
|
|
+//- Правильно
|
|
|
+app-link(to="https://example.com" target="_blank") Ссылка
|
|
|
+
|
|
|
+//- Опасно (без rel)
|
|
|
+app-link(to="https://example.com" target="_blank" rel="") Ссылка
|
|
|
+```
|
|
|
+
|
|
|
+### 3. Используйте объекты маршрутов для сложных ссылок
|
|
|
+```pug
|
|
|
+//- Правильно
|
|
|
+app-link(:to="{ name: 'EventDetail', params: { id: event._id } }") {{ event.title }}
|
|
|
+
|
|
|
+//- Менее предпочтительно
|
|
|
+app-link(:to="'/events/' + event._id") {{ event.title }}
|
|
|
+```
|
|
|
+
|
|
|
+### 4. Сохраняйте семантику контента в слоте
|
|
|
+```pug
|
|
|
+//- Правильно
|
|
|
+app-link(to="/events")
|
|
|
+ span Мероприятия
|
|
|
+ icon(name="arrow-right")
|
|
|
+
|
|
|
+//- Неправильно (не семантично)
|
|
|
+app-link(to="/events") > Мероприятия >
|
|
|
+```
|
|
|
+
|
|
|
+Компонент AppLink обеспечивает единообразное, безопасное и удобное использование ссылок во всем приложении, автоматически обрабатывая различные сценарии и предоставляя богатые возможности для кастомизации.
|