Universal Router в JavaScript предоставляет мощный и гибкий механизм маршрутизации, где каждый маршрут может иметь собственную логику и данные. Одним из ключевых инструментов для расширения возможностей маршрутов является контекст. Контекст позволяет передавать произвольные объекты и функции в обработчики маршрутов, делая маршрутизацию динамичной и настраиваемой.
Контекст в Universal Router — это объект, который передаётся в каждый
обработчик маршрута. Он создаётся при инициализации роутера и доступен
через параметр context во всех маршрутах:
import UniversalRouter from 'universal-router';
const routes = [
{
path: '/home',
action: (context) => {
return `Welcome, ${context.user.name}`;
}
}
];
const router = new UniversalRouter(routes, {
context: {
user: { name: 'Alice' },
api: {
fetchData: () => fetch('/data').then(res => res.json())
}
}
});
router.resolve('/home').then(console.log); // Output: Welcome, Alice
Ключевые моменты:
Иногда контекст необходимо модифицировать в зависимости от текущего
запроса. Для этого Universal Router поддерживает функцию
resolveContext, которая позволяет вычислять контекст
динамически:
const router = new UniversalRouter(routes, {
resolveContext: ({ pathname }) => {
return {
pathname,
user: { name: pathname.includes('admin') ? 'Admin' : 'Guest' }
};
}
});
router.resolve('/admin/dashboard').then(console.log); // Output зависит от pathname
Преимущества динамического контекста:
Universal Router позволяет объединять контексты для вложенных маршрутов. Если родительский маршрут имеет контекст, дочерние маршруты могут его расширять:
const routes = [
{
path: '/dashboard',
action: (context) => `Dashboard for ${context.user.name}`,
children: [
{
path: '/settings',
action: (context) => `Settings for ${context.user.name}, theme: ${context.theme}`
}
]
}
];
const router = new UniversalRouter(routes, {
context: {
user: { name: 'Bob' },
theme: 'dark'
}
});
router.resolve('/dashboard/settings').then(console.log);
// Output: Settings for Bob, theme: dark
Особенности объединения контекста:
Контекст удобно использовать для передачи сервисов, таких как API-клиенты, хранилища состояния или функции утилит:
const apiService = {
getUser: (id) => fetch(`/users/${id}`).then(r => r.json())
};
const router = new UniversalRouter(routes, {
context: { apiService }
});
const routes = [
{
path: '/user/:id',
action: async ({ params, apiService }) => {
const user = await apiService.getUser(params.id);
return `User: ${user.name}`;
}
}
];
Преимущества:
Universal Router полностью поддерживает асинхронные операции внутри контекста. Контекст может включать асинхронные функции, которые вызываются в момент разрешения маршрута:
const router = new UniversalRouter(routes, {
context: {
fetchUserData: async (id) => {
const response = await fetch(`/api/users/${id}`);
return await response.json();
}
}
});
const routes = [
{
path: '/profile/:id',
action: async ({ params, fetchUserData }) => {
const user = await fetchUserData(params.id);
return `Profile: ${user.name}`;
}
}
];
Особенности:
Контекст можно использовать для реализации системы авторизации и контроля доступа к маршрутам:
const router = new UniversalRouter(routes, {
context: {
user: { role: 'guest' },
requireRole: (role, context) => {
if (context.user.role !== role) {
throw new Error('Access denied');
}
}
}
});
const routes = [
{
path: '/admin',
action: ({ requireRole, context }) => {
requireRole('admin', context);
return 'Admin panel';
}
}
];
Преимущества:
Контекст в Universal Router является универсальным инструментом для передачи данных, сервисов и функций между маршрутизатором и обработчиками маршрутов. Его кастомизация открывает возможности для динамической маршрутизации, внедрения сервисов, контроля доступа и построения сложных многоуровневых приложений.