Декораторы маршрутов в Universal Router представляют собой механизм, позволяющий добавлять дополнительное поведение или метаданные к маршрутам без изменения основной логики обработки URL. Они работают как функции высокого порядка, принимающие исходный маршрут и возвращающие новый маршрут с расширенной функциональностью.
Ключевое преимущество использования декораторов заключается в возможности централизованно управлять поведением маршрутов, например, проверкой авторизации, логированием или динамическим подгрузом компонентов.
Декоратор маршрута — это функция, принимающая объект маршрута и возвращающая модифицированный объект маршрута. Типичный шаблон выглядит так:
function withAuth(route) {
return {
...route,
action: async (context) => {
if (!context.user) {
return { redirect: '/login' };
}
if (route.action) {
return route.action(context);
}
}
};
}
В данном примере декоратор withAuth проверяет
наличие пользователя в контексте. Если пользователь не авторизован,
происходит редирект на страницу логина. Если маршрут содержит
собственный action, он вызывается после проверки.
Декораторы можно использовать как для отдельного маршрута, так и для группы маршрутов.
const routes = [
{
path: '/dashboard',
action: () => 'Dashboard',
}
];
const decoratedRoutes = routes.map(withAuth);
const router = new UniversalRouter(decoratedRoutes);
Здесь маршрут /dashboard будет защищён проверкой
авторизации. Любая попытка доступа без пользователя приведёт к
редиректу.
Для маршрутов, объединённых общими правилами, можно создать функцию декоратора, применяющуюся к массиву маршрутов:
function protectRoutes(routes) {
return routes.map(withAuth);
}
const routes = protectRoutes([
{ path: '/settings', action: () => 'Settings' },
{ path: '/profile', action: () => 'Profile' }
]);
const router = new UniversalRouter(routes);
Такой подход позволяет избежать повторного дублирования логики проверки для каждого маршрута.
Декораторы можно комбинировать, применяя несколько функций к одному маршруту. Для этого используют цепочку вызовов:
function logRoute(route) {
return {
...route,
action: async (context) => {
console.log(`Переход на ${route.path}`);
return route.action ? route.action(context) : undefined;
}
};
}
const enhancedRoute = logRoute(withAuth({
path: '/dashboard',
action: () => 'Dashboard'
}));
В данном примере маршрут сначала проверяет авторизацию, а затем логирует переход. Порядок применения декораторов влияет на поведение маршрута.
Universal Router поддерживает асинхронные action,
поэтому декораторы могут выполнять отложенные операции,
такие как загрузка данных или проверка прав на сервере:
function fetchData(route, fetchFn) {
return {
...route,
action: async (context) => {
const data = await fetchFn(context);
context.data = data;
return route.action ? route.action(context) : undefined;
}
};
}
Применение такого декоратора позволяет централизованно управлять асинхронной подготовкой данных для компонентов маршрута.
Часто используют фабрики декораторов, чтобы передавать параметры при создании декоратора:
function withRole(requiredRole) {
return (route) => ({
...route,
action: (context) => {
if (!context.user || context.user.role !== requiredRole) {
return { redirect: '/unauthorized' };
}
return route.action ? route.action(context) : undefined;
}
});
}
const adminRoute = withRole('admin')({
path: '/admin',
action: () => 'Admin Panel'
});
Этот подход позволяет создавать многоразовые декораторы с разными условиями для различных маршрутов.
Декораторы легко применяются к маршрутам с дочерними маршрутами, используя рекурсивное преобразование:
function applyDecoratorRecursively(route, decorator) {
const newRoute = decorator(route);
if (route.children) {
newRoute.children = route.children.map(child => applyDecoratorRecursively(child, decorator));
}
return newRoute;
}
Таким образом, можно защитить весь сегмент маршрутов, не меняя структуру дерева маршрутов.
action для повторного использования.Эффективное использование декораторов в Universal Router позволяет построить гибкую архитектуру маршрутизации, где логика контроля доступа, подготовки данных и дополнительных действий остаётся централизованной, модульной и легко расширяемой.