Вложенные маршруты

В FAST Element маршрутизация и управление вложенными маршрутами реализуются через сочетание компонентов и реактивных свойств. Это позволяет создавать сложные интерфейсы с многоуровневой навигацией без лишнего дублирования кода. Основная идея заключается в том, что родительский компонент контролирует часть состояния маршрутов, а дочерние компоненты получают контекст и могут управлять своими собственными маршрутами.


Основы маршрутизации

FAST Element не содержит встроенного роутера, но для маршрутизации часто используются сторонние решения, такие как @microsoft/fast-router или кастомные реализации на основе window.history и popstate. Маршруты определяются как объект, где ключи — это пути, а значения — компоненты или функции, возвращающие компоненты:

const routes = {
    "/": HomePage,
    "/users": UsersPage,
    "/users/:id": UserDetailPage
};

Для вложенных маршрутов структура маршрутов может быть иерархической:

const routes = {
    "/users": {
        component: UsersPage,
        children: {
            "/:id": UserDetailPage
        }
    }
};

В этом подходе родительский маршрут отвечает за рендеринг основного контейнера, а дочерний — за содержание внутри него.


Контейнер для вложенных маршрутов

Для реализации вложенных маршрутов обычно создаётся контейнер-компонент, который рендерит дочерние маршруты. В FAST Element это реализуется через reactive properties и шаблоны с html:

import { FASTElement, html, css, customElement, observable } from "@microsoft/fast-element";

@customElement({ name: "user-page" })
export class UserPage extends FASTElement {
    @observable userId;

    static styles = css`
        .container { padding: 20px; border: 1px solid #ccc; }
    `;

    connectedCallback() {
        super.connectedCallback();
        this.updateRoute(window.location.pathname);
        window.addEventListener("popstate", () => this.updateRoute(window.location.pathname));
    }

    updateRoute(path) {
        const match = path.match(/\/users\/(\d+)/);
        this.userId = match ? match[1] : null;
    }

    render() {
        return html`
            

Детали пользователя

${this.userId ? html`` : html`

Выберите пользователя

`}
`; } }

В этом примере:

  • Свойство userId реактивное (@observable) и автоматически обновляет шаблон при изменении.
  • updateRoute разбирает текущий путь и выделяет параметр маршрута.
  • Дочерний компонент user-detail рендерится только при наличии параметра.

Передача состояния и контекста

Вложенные маршруты часто требуют передачи контекста от родителя к дочернему компоненту. В FAST Element это делается через свойства компонентов:

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


Навигация между вложенными маршрутами

Переход между маршрутами реализуется через history.pushState или сторонние роутеры:

function navigateToUser(userId) {
    history.pushState({}, "", `/users/${userId}`);
    window.dispatchEvent(new Event("popstate"));
}

При таком подходе родительский компонент автоматически поймает событие popstate, обновит реактивные свойства и рендер дочернего маршрута.


Динамическая загрузка компонентов

Для оптимизации часто используется динамический импорт дочерних компонентов:

async function loadUserDetail(userId) {
    const module = await import("./user-detail.js");
    const UserDetail = module.UserDetail;
    const container = document.querySelector("user-page");
    container.appendChild(new UserDetail({ id: userId }));
}

Это позволяет уменьшить размер начальной загрузки и инициализировать компоненты только при необходимости.


Управление вложенными маршрутами с условиями

В FAST Element можно добавлять условные маршруты внутри родителя:

${this.userId
    ? html``
    : html`

Выберите пользователя для просмотра деталей

`}

Использование тернарного оператора внутри шаблона позволяет динамически менять содержимое контейнера без перезагрузки страницы.


Рекомендации по структуре

  • Родительский компонент отвечает за контейнер и общие данные.
  • Дочерние компоненты управляют локальной логикой и визуализацией.
  • Использование реактивных свойств обеспечивает автоматический ререндер при изменении маршрутов.
  • Для сложных приложений желательно применять модули роутинга с поддержкой вложенных маршрутов и параметров.