Разделение ответственности

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


Определение и структура компонента

Компонент FAST Element строится на трёх основных уровнях: логика, шаблон и стили.

  1. Логика компонента (Class) Класс компонента наследует FASTElement и определяет реактивные свойства и методы. Пример:

    import { FASTElement, html, css, customElement } from "@microsoft/fast-element";
    
    @customElement({ name: "user-card", template: UserCard.template, styles: UserCard.styles })
    class UserCard extends FASTElement {
        firstName;
        lastName;
    
        get fullName() {
            return `${this.firstName} ${this.lastName}`;
        }
    
        greet() {
            console.log(`Привет, ${this.fullName}`);
        }
    }

    Важный аспект: класс отвечает только за состояние и поведение, но не за разметку и стили.

  2. Шаблон (HTML) Шаблон создаётся с помощью функции html и содержит привязки к свойствам класса. Пример:

    UserCard.template = html<UserCard>`
        <div class="card">
            <h2>${x => x.fullName}</h2>
            <button @click="${x => x.greet()}">Поздороваться</button>
        </div>
    `;

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

  3. Стили (CSS) Стили определяются через функцию css и применяются к шаблону. Пример:

    UserCard.styles = css`
        .card {
            border: 1px solid #ccc;
            padding: 16px;
            border-radius: 8px;
        }
        button {
            background-color: #0078d4;
            color: white;
            border: none;
            padding: 8px 12px;
            cursor: pointer;
        }
    `;

    Стили должны отдельно отвечать за визуальное оформление, не влияя на состояние и методы класса.


Реактивные свойства и их управление

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

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

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

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

class UserCard extends FASTElement {
    @observable firstName;
    @observable lastName;
}

Изменение firstName автоматически обновляет соответствующие места в шаблоне.


Обработка событий и делегирование

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

  • Шаблон привязывает событие к методу класса через @click или @change.
  • Логика внутри класса обрабатывает событие и, при необходимости, вызывает внешние события через this.$emit.

Пример:

greet() {
    const message = `Привет, ${this.fullName}`;
    this.$emit("greet", { detail: message });
}

Шаблон не знает о реализации greet — он только вызывает привязанный метод.


Композиция компонентов

FAST Element поддерживает композицию компонентов, что усиливает разделение ответственности:

  • Один компонент отвечает за отображение карточки пользователя (UserCard).
  • Другой компонент может управлять списком пользователей (UserList), используя UserCard внутри себя.
const userListTemplate = html<UserList>`
    <div>
        ${x => x.users.map(user => html`<user-card first-name="${user.firstName}" last-name="${user.lastName}"></user-card>`)}
    </div>
`;

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


Подход к состоянию и методам

  • Состояние (properties, observable) должно быть локализовано в компоненте и управляться только через него.
  • Методы выполняют бизнес-логику и изменение состояния, не вмешиваясь в рендеринг DOM.
  • DOM обновляется автоматически через биндинги, что исключает дублирование кода и смешение обязанностей.

Инкапсуляция стилей

FAST Element поддерживает Shadow DOM, что позволяет изолировать стили:

UserCard.shadowOptions = { mode: "open" };
  • Шаблон и стили изолированы, внешний CSS не влияет на внутренние элементы.
  • Логика компонента не зависит от внешних стилей.
  • Поддерживается чистое разделение визуальной части и поведения.

Использование директив для разделения визуальной и логической части

Директивы FAST (repeat, if, ref) позволяют:

  • Отделять структуру DOM от данных.
  • Минимизировать код внутри шаблона.
  • Сохранять логику в классе компонента.

Пример директивы repeat:

<ul>
    ${x => x.items.map(item => html`<li>${item}</li>`)}
</ul>
  • Шаблон не вычисляет значения — класс управляет состоянием.
  • Шаблон отвечает только за отображение.

Разделение ответственности в FAST Element создаёт чистую архитектуру: логика, шаблон, стили, события и состояние строго разграничены. Такой подход упрощает масштабирование, тестирование и сопровождение веб-приложений.