В основе маршрутизации в Page.js лежит использование API истории
браузера — history.pushState,
history.replaceState и обработка события
popstate. Это позволяет управлять URL без перезагрузки
страницы и синхронизировать состояние интерфейса с адресной строкой.
Стек истории представляет собой последовательность состояний, через которые проходит пользователь при навигации. Каждый переход добавляет или изменяет запись в этом стеке. Page.js выступает абстракцией над этим механизмом, обеспечивая удобное управление переходами и обработку маршрутов.
При обычной навигации через Page.js используется метод
pushState. Он добавляет новую запись в стек истории:
page('/about');
Внутри библиотеки это приводит к вызову:
history.pushState(state, title, path);
Ключевые особенности:
Page.js автоматически формирует объект state, содержащий
информацию о текущем маршруте, параметрах и контексте.
Иногда требуется изменить текущую запись, не добавляя новую. Для
этого используется replaceState.
В Page.js это делается через опцию:
page('/login', { replace: true });
или программно:
page.replace('/login');
Поведение:
Типичные сценарии:
При нажатии пользователем кнопок “Назад” или “Вперёд” браузер
генерирует событие popstate. Page.js автоматически
подписывается на это событие и вызывает соответствующий маршрут.
window.addEventListener('popstate', handler);
Внутри Page.js:
history.stateОсобенности:
popstate не вызывает pushStateКаждое состояние, добавляемое в стек, содержит объект
state. Page.js использует его для хранения информации о
маршруте:
{
path: '/users/42',
params: { id: '42' },
querystring: '',
title: '',
state: {}
}
Назначение:
Дополнительно можно передавать пользовательские данные:
page('/profile', { userId: 123 });
Page.js предоставляет API для управления стеком истории:
page('/dashboard');
page.replace('/dashboard');
page.redirect('/home');
redirect фактически вызывает replaceState,
чтобы избежать лишних записей в истории.
Page.js поддерживает цепочки middleware, которые могут влиять на переход:
page('/admin', authMiddleware, adminHandler);
Если middleware выполняет редирект:
function authMiddleware(ctx, next) {
if (!ctx.user) {
page.redirect('/login');
} else {
next();
}
}
Влияние на стек:
Браузер сохраняет состояние в history.state. При
возврате назад Page.js получает уже существующий объект.
Это позволяет:
Однако важно учитывать:
Page.js обеспечивает двустороннюю связь:
URL → состояние
Состояние → URL
page()Это гарантирует:
Работа со стеком истории имеет ряд ограничений:
state ограниченpopstatepushState не вызывает событие
popstatePage.js частично нивелирует эти различия, но при сложной логике навигации это необходимо учитывать.
Если используется режим с hash (#/route),
стек истории работает иначе:
page({ hashbang: true });
Особенности:
location.hashpushStateНедостатки:
При вложенной маршрутизации каждый переход создаёт отдельную запись:
page('/users', usersList);
page('/users/:id', userDetail);
Переход:
/users → /users/42
Добавляет новую запись в стек.
Если требуется избежать этого:
page.replace('/users/42');
Для анализа поведения можно использовать:
console.log(history.length);
console.log(history.state);
А также отслеживать события:
window.addEventListener('popstate', (event) => {
console.log(event.state);
});
Это помогает:
1. Лишние записи в истории
page('/step1');
page('/step2');
page('/step3');
Решение:
page.replace('/step2');
2. Потеря состояния
3. Некорректные редиректы
page() вместо
page.redirect()4. Игнорирование popstate
replace для промежуточных шаговstateПри прямом открытии URL сервер должен корректно обрабатывать маршрут:
GET /users/42
Иначе при обновлении страницы возникнет ошибка.
Обычно на сервере настраивается fallback:
* → index.html
Это гарантирует:
Page.js не скрывает полностью history, что позволяет при
необходимости:
history.pushState({ custom: true }, '', '/custom');
Но при этом важно вручную инициировать обработку маршрута:
page.show('/custom');
При перезагрузке:
Page.js повторно разбирает URL и вызывает соответствующий маршрут.
History API не управляет прокруткой автоматически. Page.js также не вмешивается в это поведение.
Рекомендуется вручную контролировать:
window.scrollTo(0, 0);
или сохранять позицию в state.
Модальные окна через историю:
page('/modal', showModal);
Закрытие:
history.back();
Многошаговые формы:
replaceStatepushStateНавигация с состоянием:
page('/search', { query: 'js' });
При каждом вызове page():
ctx)pushState или replaceStateПри popstate:
statectxИногда требуется изменить состояние приложения без изменения URL. Page.js не предоставляет прямого API для этого, но можно:
history.replaceState(newState, '', location.pathname);
Грамотное управление стеком напрямую влияет на:
Неправильная работа приводит к:
| Метод | Добавляет запись | Влияет на “Назад” | Использование |
|---|---|---|---|
| pushState | Да | Да | Обычная навигация |
| replaceState | Нет | Нет | Редиректы, корректировки |
console.log(history.length);
Позволяет отслеживать:
При разработке крупных SPA важно регулярно:
Page.js предоставляет достаточно гибкости для точного контроля, но требует внимательного подхода к архитектуре маршрутизации.