Gogs 2a38f23eb6 -- 3 週間 前
..
AppLink d100bd6170 -- 3 週間 前
README.md 2a38f23eb6 -- 3 週間 前
index.coffee df834f8c31 -- 3 週間 前
index.pug df834f8c31 -- 3 週間 前
index.styl df834f8c31 -- 3 週間 前

README.md

Компонент AppLink - Полная документация

Назначение компонента

AppLink - универсальный компонент для работы со ссылками в приложении. Автоматически определяет тип ссылки (внутренняя/внешняя) и использует соответствующий компонент (router-link для внутренних маршрутов, a для внешних URL). Обеспечивает единообразие поведения, безопасности и стилизации всех ссылок в приложении.

git репозитарий

https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/AppLink/

Импорт и регистрация

# В основном файле приложения (app/temp.coffee)
components:
    'app-link': require 'app/shared/AppLink'

Базовое использование

1. Простая внутренняя ссылка

app-link(to="/about") О нас

2. Внешняя ссылка

app-link(to="https://example.com") Внешний сайт

Полный список props

to (обязательный)

  • Тип: String | Object
  • Описание: Назначение ссылки
  • Примеры:

    //- Строковый путь
    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
  • Пример:

    app-link(href="https://example.com" to="/fallback") Ссылка
    

target (опциональный)

  • Тип: String
  • По умолчанию: '_self'
  • Допустимые значения: '_self', '_blank', '_parent', '_top'
  • Описание: Целевое окно для ссылки
  • Пример:

    app-link(to="https://example.com" target="_blank") Открыть в новом окне
    

rel (опциональный)

  • Тип: String
  • По умолчанию: ''
  • Описание: Атрибут rel для внешних ссылок
  • Примечание: Для target="_blank" автоматически добавляется noopener noreferrer
  • Пример:

    app-link(to="https://example.com" rel="nofollow") Ссылка nofollow
    

class (опциональный)

  • Тип: String | Object | Array
  • По умолчанию: ''
  • Описание: CSS классы для стилизации
  • Примеры:

    //- Строка
    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 класс для активного состояния (только для внутренних ссылок)
  • Пример:

    app-link(to="/events" active-class="bg-blue-100 text-blue-800")
    

exact (опциональный)

  • Тип: Boolean
  • По умолчанию: false
  • Описание: Точное совпадение для активного класса
  • Пример:

    app-link(to="/" exact) Главная
    

События (Events)

@click

  • Описание: Событие клика по ссылке
  • Payload: Event объект
  • Пример:

    app-link(to="/events" @click="handleEventClick")
    

Слоты (Slots)

[body] (основной слот)

  • Описание: Содержимое ссылки
  • Примеры:

    //- Текстовое содержимое
    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 - класс активного состояния (по умолчанию)

Модификаторы размера

app-link(to="/" class="app-link--sm") Маленькая
app-link(to="/" class="app-link--md") Средняя
app-link(to="/" class="app-link--lg") Большая

Варианты стилей

//- Основной стиль
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") Внешняя

Утилитарные классы

//- Без подчеркивания
app-link(to="/" class="no-underline") Без подчеркивания

//- Подчеркивание при hover
app-link(to="/" class="underline-on-hover") Подчеркивание при наведении

Примеры использования в различных сценариях

1. Навигационное меню

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. Карточки мероприятий

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. Социальные ссылки

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. Кнопки действия

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. Ссылки с параметрами запроса

app-link(
    :to="{ 
        path: '/events', 
        query: { 
            category: 'music',
            date: '2024-03'
        }
    }"
    class="text-blue-600 hover:text-blue-800"
) Музыкальные мероприятия марта

6. Ссылки с именованными маршрутами

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 и телефонные ссылки

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

Особенности работы

Автоматическое определение типа ссылки

# Внутренние ссылки
'/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

Интеграция с аналитикой

# В обработчиках событий
handleExternalClick: (event) ->
    EventBus.emit('external_link_clicked', {
        url: @normalizedHref
        target: @target
    })

handleInternalClick: (event) ->
    EventBus.emit('internal_link_clicked', {
        to: @normalizedTo
        route: @$route
    })

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

Создание собственных вариантов стилей

// В глобальных стилях
.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

Расширение функциональности

# Создание производного компонента
CustomAppLink = 
    name: 'CustomAppLink'
    extends: require 'app/shared/AppLink'
    
    methods:
        handleExternalClick: (event) ->
            # Дополнительная логика
            analytics.track('external_link_click', { url: @normalizedHref })
            
            # Вызов родительского метода
            @$super.handleExternalClick(event)

Отладка и разработка

Проверка типа ссылки

app-link(
    :to="linkUrl"
    :class="{ 'border-green-500': $el.isRouterLink, 'border-red-500': $el.isExternalLink }"
) Ссылка

Логирование событий

# В основном приложении
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 вместо прямых тегов

//- Правильно
app-link(to="/about") О нас

//- Неправильно
a(href="/about") О нас
router-link(to="/about") О нас

2. Используйте правильные target и rel для внешних ссылок

//- Правильно
app-link(to="https://example.com" target="_blank") Ссылка

//- Опасно (без rel)
app-link(to="https://example.com" target="_blank" rel="") Ссылка

3. Используйте объекты маршрутов для сложных ссылок

//- Правильно
app-link(:to="{ name: 'EventDetail', params: { id: event._id } }") {{ event.title }}

//- Менее предпочтительно
app-link(:to="'/events/' + event._id") {{ event.title }}

4. Сохраняйте семантику контента в слоте

//- Правильно
app-link(to="/events")
    span Мероприятия
    icon(name="arrow-right")

//- Неправильно (не семантично)
app-link(to="/events") > Мероприятия >

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