Universal Router в JavaScript предоставляет гибкий механизм
маршрутизации с поддержкой контекста, который
передается между маршрутами. Контекст (context) — это
объект, содержащий данные и состояния, доступные во всех обработчиках
маршрутов. Основное преимущество контекста заключается в возможности
наследования данных от родительских маршрутов к
дочерним, что упрощает управление общими состояниями приложения.
Каждый маршрут может определять свой обработчик (action)
и дополнительные данные. Контекст передается в функцию
router.resolve(context), где context может
включать такие свойства, как:
const context = {
user: { id: 1, name: 'Alice' },
auth: true
};
Если маршрут не модифицирует контекст, он наследует все свойства родительских маршрутов. Это позволяет строить дерево маршрутов, где дочерние узлы используют данные, определённые выше.
Маршруты Universal Router описываются в виде массива объектов с
полями path, action и children.
Пример:
import UniversalRouter from 'universal-router';
const routes = [
{
path: '/dashboard',
action: (context) => {
context.page = 'Dashboard';
return context.page;
},
children: [
{
path: '/stats',
action: (context) => {
return `Страница ${context.page} - Статистика`;
}
},
{
path: '/settings',
action: (context) => {
context.settingsLoaded = true;
return `Страница ${context.page} - Настройки`;
}
}
]
}
];
const router = new UniversalRouter(routes);
router.resolve('/dashboard/stats', { user: { id: 1 } })
.then(result => console.log(result));
В этом примере:
/dashboard добавляет в контекст
page./stats наследует
context.page и использует его без необходимости повторного
объявления.Universal Router передаёт контекст по цепочке маршрутов следующим образом:
context передаётся в
router.resolve.action,
получающий текущий контекст.Это позволяет строить иерархические маршруты с общим состоянием, избегая глобальных переменных.
context для данных авторизацииКонтекст идеально подходит для передачи данных, необходимых нескольким маршрутам. Например:
const routes = [
{
path: '/app',
action: (context) => {
if (!context.auth) throw new Error('Доступ запрещен');
return 'Главная';
},
children: [
{ path: '/profile', action: (ctx) => `Профиль пользователя ${ctx.user.name}` },
{ path: '/messages', action: (ctx) => `Сообщения пользователя ${ctx.user.name}` }
]
}
];
Здесь проверка авторизации происходит один раз на родительском маршруте, а дочерние маршруты используют данные пользователя через наследованный контекст.
Контекст может изменяться на лету внутри маршрутов, что делает его гибким инструментом:
const routes = [
{
path: '/shop',
action: (context) => {
context.cart = [];
return context.cart;
},
children: [
{
path: '/add/:item',
action: (context, { params }) => {
context.cart.push(params.item);
return context.cart;
}
}
]
}
];
Каждое добавление товара изменяет наследуемый объект
cart, который доступен на всех дочерних уровнях
маршрутов.
action:
Universal Router поддерживает Promise, что позволяет
загружать данные на родительском уровне перед передачей их дочерним
маршрутам.children и
parentContextПри работе с большими деревьями маршрутов полезно явно обозначать родительский контекст, если требуется использовать его в нескольких ветвях:
const routes = [
{
path: '/main',
action: (context) => {
context.theme = 'dark';
return context;
},
children: [
{
path: '/section',
action: (context, { parentContext }) => {
return `Тема приложения: ${parentContext.theme}`;
}
}
]
}
];
Поле parentContext предоставляет неизменённый
объект родителя, что помогает избегать конфликтов при
динамическом изменении контекста на дочерних маршрутах.
Наследование контекста в Universal Router делает маршрутизацию структурированной и предсказуемой. Контекст обеспечивает:
Использование этого механизма позволяет создавать масштабируемые и легко поддерживаемые приложения с чистой иерархией маршрутов.