Библиотека Page.js представляет собой легковесный роутер для одностраничных приложений (SPA) на JavaScript. Основная её задача — управление навигацией без перезагрузки страницы. В контексте управления компонентами это особенно важно: каждый маршрут должен корректно отображать соответствующий компонент, обеспечивая плавные переходы и освобождение ресурсов предыдущих представлений.
Регистрация маршрутов происходит с помощью функции
page(path, callback). Пример базовой настройки:
page('/', () => renderHome());
page('/about', () => renderAbout());
page();
Здесь renderHome и renderAbout — функции,
отвечающие за отрисовку компонентов. Важно понимать, что Page.js
не управляет DOM автоматически; ответственность за очистку или
обновление элементов лежит на разработчике.
Для эффективного управления компонентами рекомендуется централизовать
точку монтирования, например, один контейнер
<div id="app"></div>. Все маршруты будут
рендерить свои компоненты внутрь этого контейнера:
const app = document.getElementById('app');
function renderComponent(component) {
app.innerHTML = '';
app.appendChild(component);
}
function renderHome() {
const homeDiv = document.createElement('div');
homeDiv.textContent = 'Главная страница';
renderComponent(homeDiv);
}
function renderAbout() {
const aboutDiv = document.createElement('div');
aboutDiv.textContent = 'О сайте';
renderComponent(aboutDiv);
}
Такой подход гарантирует, что при каждом переходе предыдущий компонент будет удалён, а новый корректно отображён.
Page.js позволяет добавлять промежуточные функции (middleware), которые выполняются перед основным обработчиком маршрута. Middleware полезны для:
Пример middleware:
function auth(ctx, next) {
if (!userIsLoggedIn()) {
page.redirect('/login');
} else {
next();
}
}
page('/dashboard', auth, () => {
renderDashboard();
});
Параметр ctx содержит информацию о текущем маршруте,
включая путь, параметры и состояние запроса, что удобно для передачи
данных между middleware и компонентом.
Для SPA важно не просто менять содержимое контейнера, но и
обеспечивать анимацию и сохранение состояния. Один из
способов — хранение текущего компонента и вызов его методов
beforeLeave или destroy перед рендером
нового:
let currentComponent = null;
function render(component) {
if (currentComponent && currentComponent.destroy) {
currentComponent.destroy();
}
currentComponent = component;
app.innerHTML = '';
app.appendChild(component.element);
}
function createComponent(content) {
return {
element: (() => {
const div = document.createElement('div');
div.textContent = content;
return div;
})(),
destroy() {
console.log('Компонент удалён');
}
};
}
page('/', () => render(createComponent('Главная')));
page('/about', () => render(createComponent('О сайте')));
Такой паттерн позволяет легко интегрировать анимации или таймеры в компоненты, корректно очищая их при уходе со страницы.
Page.js поддерживает динамические сегменты маршрута, которые удобно использовать для отображения детальных страниц:
page('/user/:id', ctx => {
const userId = ctx.params.id;
renderUserProfile(userId);
});
Параметры маршрута (ctx.params) обеспечивают доступ к
переменным в URL, а middleware можно использовать для предварительной
загрузки данных:
function loadUser(ctx, next) {
fetch(`/api/users/${ctx.params.id}`)
.then(res => res.json())
.then(data => {
ctx.userData = data;
next();
});
}
page('/user/:id', loadUser, ctx => {
renderUserProfile(ctx.userData);
});
Для сложных интерфейсов часто необходимо иметь вложенные маршруты. Page.js поддерживает каскадное выполнение middleware, что позволяет управлять как глобальными контейнерами, так и дочерними компонентами:
page('/dashboard', ctx => renderDashboard(ctx));
page('/dashboard/settings', ctx => renderSettings(ctx));
Использование одного контейнера для родительского компонента и отдельного для дочерних элементов упрощает логику обновления и позволяет интегрировать анимации переходов только для изменяющихся частей интерфейса.
Эти методы помогают сделать SPA более отзывчивым и сохранить ресурсы браузера, особенно при большом количестве маршрутов и сложных компонентах.
Такой подход обеспечивает четкое управление компонентами, упрощает поддержку SPA и делает переходы между страницами предсказуемыми и контролируемыми.