Universal Router — это гибкая библиотека маршрутизации для JavaScript, которая позволяет создавать маршруты для приложений любого типа: веб, Node.js, серверных и изоморфных приложений. Одной из ключевых возможностей является обработка событий навигации, которая позволяет контролировать переходы между маршрутами, управлять асинхронной логикой и выполнять действия до или после изменения URL.
Каждый маршрут в Universal Router определяется объектом с
обязательным свойством path и функцией
action:
const routes = [
{
path: '/',
action: () => 'Главная страница'
},
{
path: '/about',
action: () => 'О сайте'
},
{
path: '/user/:id',
action: ({ params }) => `Профиль пользователя ${params.id}`
}
];
const router = new UniversalRouter(routes);
Ключевые моменты:
path поддерживает динамические сегменты
(:id) и регулярные выражения.action вызывается при совпадении маршрута и получает
объект context, содержащий параметры, путь и другие
данные.router.resolve(path).Universal Router позволяет обрабатывать навигацию через хуки — функции, которые выполняются до или после перехода. Основные сценарии использования:
const routes = [
{
path: '/dashboard',
action: ({ router }) => 'Панель управления',
before: async ({ context }) => {
const isAuthenticated = await checkAuth();
if (!isAuthenticated) {
return router.resolve('/login');
}
}
},
{ path: '/login', action: () => 'Страница входа' }
];
Особенности работы before:
undefined, переход продолжается к
action.Контекст (context) — объект, передаваемый каждому
маршруту и хукам. Важные свойства:
pathname — текущий путь.params — параметры динамических сегментов.router — ссылка на экземпляр Universal Router, полезно
для вызова router.resolve внутри маршрута или хука.query — объект с query-параметрами (при интеграции с
URLSearchParams).Пример использования параметров и query:
const routes = [
{
path: '/search/:term',
action: ({ params, query }) => {
return `Результаты поиска по "${params.term}", фильтр: ${query.filter}`;
}
}
];
router.resolve('/search/javascript?filter=recent');
Universal Router полностью поддерживает асинхронные функции в
action и before. Это позволяет выполнять:
Пример асинхронного маршрута:
const routes = [
{
path: '/profile/:id',
async action({ params }) {
const user = await fetchUser(params.id);
if (!user) return 'Пользователь не найден';
return `Имя пользователя: ${user.name}`;
}
}
];
Для клиентских приложений на браузере часто требуется реагировать на
все изменения маршрута. Это можно сделать, оборачивая вызовы
router.resolve:
async function navigate(path) {
console.log('Переход на:', path);
const result = await router.resolve(path);
console.log('Результат маршрута:', result);
render(result);
}
Редирект в Universal Router осуществляется возвратом нового маршрута
из action или before:
const routes = [
{
path: '/old-page',
action: ({ router }) => router.resolve('/new-page')
},
{ path: '/new-page', action: () => 'Новая страница' }
];
Важно:
router.resolve для условного
редиректа, например, после проверки состояния пользователя.Universal Router позволяет обрабатывать ситуации, когда маршрут не найден или происходит ошибка:
router.resolve('/unknown').catch(error => {
if (error.name === 'NavigationError') {
console.log('Маршрут не найден');
} else {
console.error('Ошибка при навигации:', error);
}
});
Особенности:
action или
before, можно ловить через catch.router.resolve в функцию, которая логирует или отображает
страницу ошибки.Для SPA важно синхронизировать навигацию с браузерной историей:
window.addEventListener('popstate', () => {
router.resolve(window.location.pathname);
});
function navigateTo(path) {
history.pushState(null, '', path);
router.resolve(path);
}
pushState позволяет изменять URL без
полной перезагрузки страницы.popstate обеспечивает обработку кнопок
назад/вперед.before.Universal Router обеспечивает полный контроль над навигацией в приложении, предоставляя гибкие механизмы асинхронного перехвата, редиректов и обработки ошибок. Правильная организация маршрутов и хуков позволяет создавать устойчивые и масштабируемые клиентские и серверные приложения на JavaScript.