Page.js — это небольшая клиентская библиотека для управления маршрутизацией в одностраничных приложениях (SPA) на JavaScript. Важным аспектом при работе с Page.js является правильная организация иерархии путей. Это позволяет создавать масштабируемые и легко поддерживаемые приложения.
Маршруты в Page.js определяются функцией
page(path, callback). Здесь path — это строка
маршрута, а callback — функция, которая выполняется при
переходе на указанный путь.
Пример базового маршрута:
page('/about', () => {
console.log('Страница "О проекте"');
});
Для организации вложенной структуры страниц используется определение маршрутов с общим префиксом. Это позволяет создавать иерархические структуры, где родительский маршрут задаёт контекст, а дочерние маршруты уточняют содержание.
Пример:
page('/dashboard', () => {
console.log('Главная панель');
});
page('/dashboard/settings', () => {
console.log('Настройки панели');
});
page('/dashboard/profile', () => {
console.log('Профиль пользователя');
});
В этом примере /dashboard является родительским
маршрутом, а /dashboard/settings и
/dashboard/profile — дочерними. Такой подход упрощает
добавление новых разделов и поддержание согласованности URL.
Page.js поддерживает динамические сегменты, которые позволяют
создавать маршруты с параметрами. Параметры задаются через двоеточие
(:), и значения параметров автоматически передаются в
объект ctx.params внутри callback-функции.
Пример:
page('/users/:userId', (ctx) => {
console.log(`ID пользователя: ${ctx.params.userId}`);
});
page('/users/:userId/posts/:postId', (ctx) => {
console.log(`Пользователь ${ctx.params.userId}, пост ${ctx.params.postId}`);
});
Динамические маршруты идеально подходят для вложенной структуры, где одни и те же компоненты могут обслуживать разные идентификаторы.
Page.js позволяет использовать middleware-функции для обработки маршрутов до вызова основного callback. Middleware удобно применять для реализации авторизации, загрузки данных или общего поведения для группы маршрутов.
Пример с middleware для всех маршрутов внутри
/dashboard:
function requireAuth(ctx, next) {
if (!ctx.user) {
page.redirect('/login');
} else {
next();
}
}
page('/dashboard*', requireAuth); // звездочка '*' позволяет применить middleware ко всем дочерним маршрутам
page('/dashboard', () => console.log('Главная панель'));
page('/dashboard/settings', () => console.log('Настройки'));
Использование префикса с * — мощный инструмент для
группировки маршрутов и реализации общей логики для всего раздела.
Вложенные маршруты могут иметь собственные middleware, которые будут вызываться после middleware родителя. Это позволяет строить многоуровневую обработку запросов.
page('/dashboard', requireAuth, (ctx, next) => {
console.log('Главная панель');
next();
});
function settingsMiddleware(ctx, next) {
console.log('Загружаем настройки');
next();
}
page('/dashboard/settings', settingsMiddleware, (ctx) => {
console.log('Страница настроек');
});
Таким образом, для маршрута /dashboard/settings
последовательно вызываются requireAuth,
settingsMiddleware и основной callback.
Для удобства и удобочитаемости большие приложения могут строить маршруты через массивы объектов:
const routes = [
{ path: '/', callback: () => console.log('Главная') },
{ path: '/about', callback: () => console.log('О проекте') },
{
path: '/dashboard',
middleware: [requireAuth],
children: [
{ path: '', callback: () => console.log('Панель') },
{ path: '/settings', callback: () => console.log('Настройки') },
{ path: '/profile', callback: () => console.log('Профиль') },
]
}
];
function registerRoutes(routeArray, parent = '') {
routeArray.forEach(route => {
const fullPath = parent + route.path;
const handlers = [...(route.middleware || []), route.callback];
page(fullPath, ...handlers);
if (route.children) {
registerRoutes(route.children, fullPath);
}
});
}
registerRoutes(routes);
Такой подход упрощает масштабирование, добавление новых маршрутов и поддержание иерархии.
Для обработки несуществующих страниц или динамических путей
используется символ * в конце маршрута:
page('*', () => {
console.log('Страница не найдена');
});
Также можно комбинировать динамические параметры и wildcard:
page('/blog/:slug*', (ctx) => {
console.log(`Статья: ${ctx.params.slug}`);
});
/dashboard/settings всегда относится к
/dashboard.Иерархическая организация маршрутов в Page.js повышает читаемость кода, упрощает поддержку и расширение приложения, а также обеспечивает централизованное управление логикой для группы связанных страниц.