Композитные компоненты

FAST Element — это библиотека для создания веб-компонентов на базе стандартов Web Components, предоставляющая мощные возможности для построения сложных и повторно используемых интерфейсов. Одним из ключевых инструментов в разработке масштабных приложений являются композитные компоненты, которые позволяют объединять несколько компонентов в один логический блок, сохраняя управляемость состояния и гибкость стилизации.


Основные концепции композитных компонентов

Композитный компонент в FAST Element — это компонент, который состоит из одного или нескольких дочерних компонентов, взаимодействующих между собой через свойства, события и слоты. Основные особенности:

  • Инкапсуляция логики и разметки. Внутренняя структура компонента скрыта от внешнего мира, взаимодействие происходит только через публичные API: свойства, методы и события.
  • Повторное использование. Композитные компоненты позволяют объединять базовые компоненты в единый блок и использовать его многократно.
  • Слоты и шаблоны. FAST Element поддерживает именованные и неименованные слоты, что позволяет вставлять произвольный контент внутрь компонента.

Создание композитного компонента

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

Пример структуры простого композитного компонента:

import { FASTElement, html, css } from "@microsoft/fast-element";
import "./button.js";
import "./input.js";

const template = html`
  <div class="composite-container">
    <my-input value="${x => x.inputValue}" @input="${x => x.onInput()}"></my-input>
    <my-button @click="${x => x.onSubmit()}">Отправить</my-button>
  </div>
`;

const styles = css`
  .composite-container {
    display: flex;
    gap: 10px;
    align-items: center;
  }
`;

export class FormComponent extends FASTElement {
  inputValue = "";

  onInput(event) {
    this.inputValue = event.target.value;
  }

  onSubmit() {
    console.log("Отправлено значение:", this.inputValue);
  }
}

FormComponent.define({
  name: "form-component",
  template,
  styles
});

В этом примере FormComponent объединяет my-input и my-button, обрабатывая события и связывая состояние между ними.


Связь между дочерними компонентами

Композитные компоненты в FAST Element реализуют двунаправленное взаимодействие через:

  1. Свойства (Properties) — основной способ передачи данных вниз по иерархии.
  2. События (Events) — механизм уведомления родителя о действиях дочернего компонента.
  3. Слоты (Slots) — вставка произвольного контента или других компонентов.

Пример передачи данных через свойства и события:

<child-component
  .value="${parentValue}"
  @value-changed="${x => x.handleChildChange()}">
</child-component>

Здесь parentValue передается дочернему компоненту, а любое изменение значения инициирует событие value-changed, которое обрабатывает родитель.


Использование слотов в композитных компонентах

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

Пример композитного компонента с именованными слотами:

const template = html`
  <div class="card">
    <header><slot name="header"></slot></header>
    <main><slot></slot></main>
    <footer><slot name="footer"></slot></footer>
  </div>
`;

export class CardComponent extends FASTElement {}

CardComponent.define({
  name: "card-component",
  template
});

Использование:

<card-component>
  <h1 slot="header">Заголовок</h1>
  <p>Основной контент</p>
  <button slot="footer">Действие</button>
</card-component>

Такой подход делает компонент максимально гибким и настраиваемым.


Взаимодействие с реактивными свойствами

FAST Element предоставляет реактивные свойства, которые автоматически обновляют DOM при изменении состояния. Это особенно полезно для композитных компонентов, где несколько дочерних компонентов зависят от общего состояния.

Пример реактивного свойства:

import { observable } from "@microsoft/fast-element";

export class CounterComponent extends FASTElement {
  @observable count = 0;

  increment() {
    this.count += 1;
  }
}

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


Стратегии организации больших композитных компонентов

При создании сложных UI с множеством дочерних компонентов стоит придерживаться нескольких принципов:

  • Разделение ответственности. Каждый дочерний компонент выполняет строго определённую функцию.
  • Минимизация связей. Использовать события для уведомления о действиях, а не прямой доступ к внутренним методам дочерних компонентов.
  • Переиспользуемые шаблоны. Часто повторяющиеся блоки лучше оформлять как отдельные компоненты и подключать через слоты.
  • Стилизация через Shadow DOM. Инкапсуляция стилей предотвращает конфликт с внешней разметкой.

Директивы FAST в композитных компонентах

FAST поддерживает директивы, упрощающие управление состоянием внутри шаблонов:

  • repeat — для генерации списков.
  • if — условный рендеринг.
  • ref — получение ссылки на DOM-элемент или дочерний компонент.
  • when — сложные условия отображения.

Пример с директивой repeat:

const template = html`
  <ul>
    ${repeat(x => x.items, html`<li>${x => x}</li>`)}
  </ul>
`;

Это позволяет композитному компоненту динамически отображать списки без ручного манипулирования DOM.


Передача состояния между композитными компонентами

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

  • Использование глобального состояния через Store или реактивные объекты.
  • Передача состояния через свойства при вложенности компонентов.
  • Использование событий для уведомления о изменениях.

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


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