Навигация с сохранением истории

Page.js — это лёгкая клиентская библиотека для реализации маршрутизации в одностраничных приложениях (SPA) на JavaScript. Она позволяет управлять историей браузера, изменять URL без перезагрузки страницы и связывать URL с определёнными обработчиками функций.

Подключение и инициализация

Для работы с Page.js необходимо подключить скрипт к проекту. Обычно используют версию через CDN:

<script src="https://unpkg.com/page/page.js"></script>

Инициализация маршрутов производится через функцию page(). Основная структура выглядит так:

page('/home', () => {
    console.log('Home page');
});

page('/about', () => {
    console.log('About page');
});

page();

Последний вызов page() запускает наблюдение за изменением URL и обработку маршрутов.


Определение маршрутов

Маршрут определяется URL-паттерном и функцией-обработчиком:

page('/products', () => {
    renderProductsList();
});

page('/products/:id', ctx => {
    console.log('Product ID:', ctx.params.id);
});
  • :id — параметр маршрута, значение которого доступно через объект ctx.params.
  • ctx содержит информацию о текущем состоянии маршрута, включая path, params, querystring и другие полезные свойства.

Преимущества параметров маршрутов:

  • Возможность создания динамических страниц на основе URL.
  • Простота передачи данных в обработчики без глобальных переменных.

Обработка query-параметров

Page.js не разбирает query-параметры автоматически, но они доступны через ctx.querystring:

page('/search', ctx => {
    const params = new URLSearchParams(ctx.querystring);
    const term = params.get('q');
    console.log('Search term:', term);
});

Использование URLSearchParams позволяет легко извлекать значения и работать с фильтрацией или пагинацией.


Навигация без перезагрузки страницы

Для переходов между маршрутами используют функцию page.show():

page.show('/about');

Это позволяет изменять URL и запускать соответствующие обработчики, не вызывая полной перезагрузки страницы. В SPA это критично для поддержания состояния приложения и быстрого отклика интерфейса.


Middleware и последовательная обработка

Page.js поддерживает цепочку middleware, что позволяет добавлять промежуточные функции для проверки состояния или подготовки данных:

page((ctx, next) => {
    console.log('Logging:', ctx.path);
    next();
});

page('/dashboard', (ctx, next) => {
    if (!isLoggedIn()) {
        page.redirect('/login');
    } else {
        next();
    }
}, () => {
    renderDashboard();
});
  • Middleware вызывается последовательно.
  • next() передаёт управление следующей функции в цепочке.
  • Это удобно для авторизации, логирования, анимаций перехода и предварительной загрузки данных.

Перенаправления и управление историей

Page.js предоставляет методы для контроля истории браузера:

  • page.redirect(path) — заменяет текущий URL новым и вызывает обработчик маршрута.
  • page.replace(path) — заменяет текущий URL без добавления новой записи в историю, что полезно для редиректов при проверке условий.

Пример редиректа при отсутствии авторизации:

page('/profile', ctx => {
    if (!isLoggedIn()) {
        page.redirect('/login');
    } else {
        renderProfile();
    }
});

Обработка ошибок маршрутизации

Если маршрут не найден, можно задать обработчик по умолчанию:

page('*', () => {
    renderNotFoundPage();
});

Символ * действует как wildcard, позволяя перехватывать все неизвестные URL.


Поддержка HTML5 History API

Page.js работает с HTML5 History API (pushState, replaceState) для сохранения истории переходов. Это обеспечивает:

  • Возможность использовать «Назад» и «Вперед» браузера.
  • Изменение URL без перезагрузки страницы.
  • Чистый и семантичный URL.

Пример использования вместе с обработкой кнопок браузера:

window.onpopst ate = function() {
    page(window.location.pathname + window.location.search);
};

Асинхронная загрузка данных и рендеринг

Page.js отлично сочетается с асинхронными вызовами:

page('/users/:id', async ctx => {
    const userData = await fetchUserData(ctx.params.id);
    renderUserProfile(userData);
});

Использование async/await в обработчиках маршрутов позволяет:

  • Загружать данные до рендеринга компонента.
  • Сохранять плавность навигации без блокировки интерфейса.

Гибкая организация маршрутов

Маршруты можно группировать и выносить в отдельные модули:

import { dashboardRoutes } from './dashboardRoutes.js';
import { authRoutes } from './authRoutes.js';

dashboardRoutes.forEach(route => page(route.path, ...route.handlers));
authRoutes.forEach(route => page(route.path, ...route.handlers));

page();

Такой подход упрощает поддержку и масштабирование крупных SPA-проектов.


Основные методы Page.js

Метод Описание
page(path, handler) Определяет маршрут с обработчиком
page.show(path) Переход на маршрут без перезагрузки
page.redirect(path) Перенаправление с добавлением записи в историю
page.replace(path) Замена текущей записи в истории
page() Инициализация маршрутов и запуск наблюдения за URL
page('*', handler) Обработчик для всех неизвестных маршрутов

Использование Page.js позволяет строить чистую навигацию с сохранением истории браузера, обеспечивая полноценный SPA-подход с динамическим изменением контента, поддержкой middleware и гибкой маршрутизацией.