В Universal Router маршрутизация строится вокруг концепции цепочки middleware, где каждый маршрут может определять обработчик, а также дополнительные функции, которые выполняются до или после основного обработчика. Понимание порядка выполнения этих функций критично для корректной работы приложения, особенно при реализации авторизации, логирования или динамического построения контента.
Сопоставление маршрута (route matching)
Universal Router сначала пытается найти маршрут, соответствующий
текущему URL. Алгоритм поиска происходит сверху вниз по списку
маршрутов. Каждый маршрут проверяется на соответствие шаблону
path. Если маршрут содержит вложенные маршруты
(children), проверка продолжается рекурсивно.
Особенность: маршруты с более точным соответствием
имеют приоритет перед маршрутами с параметрами или wildcard
(*).
Вызов middleware через beforeEnter или
resolve Для каждого маршрута можно определить
функцию beforeEnter(context, next),
которая выполняется перед основным обработчиком
маршрута. Эта функция может:
return router.resolve('/new-path');next() для продолжения выполнения
цепочки.Если beforeEnter возвращает значение, оно прерывает
стандартный вызов resolve для этого маршрута и используется
как результат маршрутизации.
Обработка основного resolve
маршрута Основная функция
resolve(context, params) выполняется после
прохождения всех beforeEnter. Здесь обрабатывается:
HTML, JSON и
т.д.);Важно: если resolve возвращает промис,
Universal Router дожидается его выполнения, что позволяет использовать
асинхронные операции, такие как загрузка данных с сервера.
Вызов вложенных маршрутов (children) После
выполнения resolve маршрута Universal Router проверяет
наличие дочерних маршрутов в свойстве children. Порядок
выполнения дочерних маршрутов аналогичен: сначала
beforeEnter, затем resolve.
Принцип каскада: родительский маршрут должен
завершить свои middleware до того, как будут вызваны middleware дочерних
маршрутов. Это обеспечивает возможность установки контекста
(context) для всех вложенных обработчиков.
Middleware глобального уровня Помимо middleware на уровне отдельных маршрутов, Universal Router позволяет реализовать глобальные обработчики, например через обертку маршрутизатора:
const router = new UniversalRouter(routes, {
resolveRoute(context, route) {
// глобальная логика перед вызовом route.resolve
if (route.resolve) return route.resolve(context, route.params);
}
});
Глобальные middleware выполняются до вызова конкретного
resolve маршрута, что позволяет реализовать
универсальные проверки (авторизация, логирование).
beforeEnter или resolve маршрута может
полностью остановить дальнейшее выполнение, включая дочерние
маршруты.router.resolve('/another') внутри middleware создает новый
цикл маршрутизации, который также учитывает порядок
beforeEnter и resolve.context передается через всю цепочку middleware и может
модифицироваться на каждом уровне, что обеспечивает гибкость передачи
данных между родительскими и дочерними маршрутами.beforeEnter, чтобы дочерние маршруты
автоматически наследовали проверку.const routes = [
{
path: '/dashboard',
beforeEnter: async (ctx, next) => {
if (!ctx.user) return '/login';
return next();
},
resolve: async (ctx) => {
const data = await fetchDashboardData(ctx.user.id);
return { template: 'dashboard', data };
},
children: [
{
path: 'settings',
resolve: (ctx) => ({ template: 'settings', data: ctx.user.settings })
}
]
}
];
Порядок вызова для
/dashboard/settings:
beforeEnter родительского маршрута
/dashboardresolve родительского маршрута /dashboard
(загрузка данных дашборда)settingsresolve дочернего маршрута settingsКонтекст ctx передается на каждом шаге и может
использоваться всеми уровнями маршрутов.
Этот механизм позволяет точно контролировать, какие middleware и в каком порядке выполняются, обеспечивая гибкую и предсказуемую маршрутизацию приложений на Universal Router.