Управление компонентами при переходах

Библиотека 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);
}

Такой подход гарантирует, что при каждом переходе предыдущий компонент будет удалён, а новый корректно отображён.

Использование middleware для управления состоянием

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));

Использование одного контейнера для родительского компонента и отдельного для дочерних элементов упрощает логику обновления и позволяет интегрировать анимации переходов только для изменяющихся частей интерфейса.

Оптимизация рендеринга

  • Использование виртуального DOM или библиотек типа lit-html или React совместно с Page.js упрощает управление компонентами при переходах.
  • Минимизация перерисовки элементов за счёт целевого обновления контейнеров.
  • Поддержка кэширования данных между переходами, чтобы повторно не загружать компоненты и API.

Эти методы помогают сделать SPA более отзывчивым и сохранить ресурсы браузера, особенно при большом количестве маршрутов и сложных компонентах.

Итоговая структура приложения с Page.js

  1. Единый контейнер для рендеринга компонентов.
  2. Централизованные функции создания и очистки компонентов.
  3. Middleware для проверки состояния и загрузки данных.
  4. Управление текущим компонентом для плавных переходов и анимаций.
  5. Использование динамических маршрутов и вложенных маршрутов для сложной структуры интерфейса.
  6. Оптимизация рендеринга и кэширование данных для производительности.

Такой подход обеспечивает четкое управление компонентами, упрощает поддержку SPA и делает переходы между страницами предсказуемыми и контролируемыми.