Breadcrumbs

Breadcrumbs (хлебные крошки) представляют собой последовательность навигационных ссылок, отражающую путь пользователя по приложению. В контексте Universal Router они позволяют отслеживать текущий маршрут и строить динамическую навигацию на основе конфигурации маршрутов.

Принципы работы

В Universal Router каждый маршрут описывается объектом с ключевыми свойствами:

  • path — шаблон пути маршрута;
  • action — функция, выполняемая при совпадении маршрута;
  • children — вложенные маршруты, позволяющие создавать иерархию.

Breadcrumbs строятся путем последовательного прохода по маршрутам от корня к конечному маршруту, учитывая вложенные маршруты и параметры.

Пример структуры маршрутов с поддержкой хлебных крошек:

const routes = [
  {
    path: '/',
    action: () => 'Главная',
    children: [
      {
        path: '/products',
        action: () => 'Продукты',
        children: [
          {
            path: '/products/:id',
            action: ({ params }) => `Продукт ${params.id}`,
          }
        ]
      },
      {
        path: '/about',
        action: () => 'О компании',
      }
    ]
  }
];

Генерация Breadcrumbs

Для построения хлебных крошек требуется:

  1. Разрешить маршрут с помощью router.resolve.
  2. Пройти по цепочке маршрутов, используя поле route.
  3. Извлечь ключевую информацию (path и action) для каждой ступени.

Пример функции генерации:

import UniversalRouter from 'universal-router';

const router = new UniversalRouter(routes);

async function getBreadcrumbs(url) {
  const match = await router.resolve({ pathname: url });
  const breadcrumbs = [];

  let currentRoute = match.route;
  while (currentRoute) {
    const label = await currentRoute.action({ params: match.params });
    breadcrumbs.unshift({ path: currentRoute.path, label });
    currentRoute = currentRoute.parent;
  }

  return breadcrumbs;
}

getBreadcrumbs('/products/42').then(console.log);
/*
[
  { path: '/', label: 'Главная' },
  { path: '/products', label: 'Продукты' },
  { path: '/products/:id', label: 'Продукт 42' }
]
*/

Вложенные маршруты и динамические параметры

Важный аспект работы хлебных крошек — поддержка динамических параметров. В примере выше маршрут /products/:id позволяет подставлять идентификатор продукта в подпись хлебной крошки. Universal Router автоматически передает параметры в action, что облегчает генерацию динамических названий.

При сложной иерархии рекомендуется:

  • Использовать поле parent для указания родительского маршрута;
  • Избегать циклических ссылок в маршрутах;
  • Формировать label через функции, принимающие params и query.

Пример расширенной конфигурации

const routes = [
  {
    path: '/',
    action: () => 'Главная',
    children: [
      {
        path: '/users',
        action: () => 'Пользователи',
        children: [
          {
            path: '/users/:userId',
            action: ({ params }) => `Профиль ${params.userId}`,
            children: [
              {
                path: '/users/:userId/settings',
                action: () => 'Настройки',
              }
            ]
          }
        ]
      }
    ]
  }
];

Запрос '/users/7/settings' сгенерирует хлебные крошки:

Главная > Пользователи > Профиль 7 > Настройки

Советы по оптимизации

  • Кэширование результатов: если приложение большое, можно кэшировать сгенерированные хлебные крошки по маршруту для ускорения рендеринга.
  • Асинхронные action: Universal Router поддерживает промисы, поэтому можно загружать данные (например, имена пользователей) перед формированием хлебных крошек.
  • SEO и семантика: использовать элементы <nav> и <ol> с aria-label="Breadcrumb" для улучшения доступности и индексации поисковиками.

Поддержка международных версий

Для мультиязычных приложений рекомендуется хранить локализованные лейблы отдельно и передавать их в action:

action: ({ params, i18n }) => i18n.t('product', { id: params.id })

где i18n — объект локализации, доступный через контекст маршрута.

Итоговая структура

Эффективная реализация хлебных крошек в Universal Router строится на трех ключевых принципах:

  1. Иерархичность маршрутов с вложенными children.
  2. Динамические подписи через функцию action.
  3. Последовательный проход от корня до конечного маршрута для формирования цепочки навигации.

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