FAST Element — это библиотека для построения веб-компонентов на базе стандарта Custom Elements, обеспечивающая реактивность, шаблонизацию и эффективное управление состоянием. Одним из ключевых подходов для организации логики компонентов является паттерн контроллеров. Контроллеры позволяют разделять ответственность между визуальной частью компонента и функциональной логикой, облегчая повторное использование кода и тестирование.
Контроллеры представляют собой объекты, которые управляют поведением компонента, реагируют на изменения свойств, событий и жизненного цикла, не вмешиваясь напрямую в DOM-структуру компонента. Основное преимущество такого подхода — разделение ответственности: компонент отвечает за отображение, контроллер — за логику.
Контроллер должен реализовывать интерфейс
FASTElementController или использовать типовую структуру с
методами жизненного цикла:
class ExampleController {
constructor(host) {
this.host = host; // ссылка на компонент
}
connectedCallback() {
console.log('Контроллер подключен к компоненту');
}
disconnectedCallback() {
console.log('Контроллер отсоединен от компонента');
}
hostUpdated() {
console.log('Свойства компонента изменились');
}
}
constructor(host) — принимает ссылку на компонент, к
которому привязан контроллер.connectedCallback() — вызывается, когда компонент
подключен к DOM.disconnectedCallback() — вызывается при удалении
компонента из DOM.hostUpdated() — вызывается после обновления реактивных
свойств компонента.FAST Element предоставляет метод addController для
регистрации контроллера внутри компонента:
import { FASTElement, html } from "@microsoft/fast-element";
class MyComponent extends FASTElement {
constructor() {
super();
this.addController(new ExampleController(this));
}
static template = html`<div>Пример компонента</div>`;
}
Вызов addController обеспечивает автоматический вызов
методов жизненного цикла контроллера: connectedCallback,
disconnectedCallback, hostUpdated.
Контроллер может реагировать на изменения свойств компонента,
используя метод hostUpdated(). Для фильтрации изменений
конкретных свойств можно хранить предыдущие значения:
class PropertyWatcherController {
constructor(host) {
this.host = host;
this.prevValue = host.value;
}
hostUpdated() {
if (this.host.value !== this.prevValue) {
console.log(`Свойство изменилось с ${this.prevValue} на ${this.host.value}`);
this.prevValue = this.host.value;
}
}
}
Такой подход позволяет создавать контроллеры для валидации, форматирования данных, управления состояниями UI без загрязнения основного кода компонента.
Контроллеры могут подписываться на события компонента или
DOM-элементов внутри него. В connectedCallback удобно
добавлять слушатели:
class EventController {
constructor(host) {
this.host = host;
this.handleClick = this.handleClick.bind(this);
}
connectedCallback() {
this.host.addEventListener('click', this.handleClick);
}
disconnectedCallback() {
this.host.removeEventListener('click', this.handleClick);
}
handleClick(event) {
console.log('Клик по компоненту', event);
}
}
Методы connectedCallback и
disconnectedCallback обеспечивают корректное подключение и
очистку обработчиков, предотвращая утечки памяти.
Один компонент может использовать несколько контроллеров одновременно. Порядок вызова методов жизненного цикла контроллеров соответствует порядку их добавления:
class ComponentWithControllers extends FASTElement {
constructor() {
super();
this.addController(new EventController(this));
this.addController(new PropertyWatcherController(this));
}
}
Множественные контроллеры помогают организовать сложную логику компонента, разделяя разные аспекты функциональности: работу с событиями, синхронизацию с сервером, управление внутренним состоянием.
Контроллеры можно использовать в нескольких компонентах, что делает их модульными и легко тестируемыми. Например, контроллер для управления анимацией или валидацией формы может быть создан один раз и применяться к любому компоненту с аналогичным поведением.
class AnimationController {
constructor(host, animationName) {
this.host = host;
this.animationName = animationName;
}
connectedCallback() {
this.host.classList.add(this.animationName);
}
disconnectedCallback() {
this.host.classList.remove(this.animationName);
}
}
Контроллеры взаимодействуют с шаблонами через свойства компонента или через ref-атрибуты для получения доступа к элементам DOM внутри компонента:
class DomController {
constructor(host) {
this.host = host;
}
hostUpdated() {
const input = this.host.shadowRoot.querySelector('input');
if (input) {
input.value = this.host.value.toUpperCase();
}
}
}
Такой подход позволяет сохранять реактивность и не смешивать логику с шаблоном напрямую.
Использование контроллеров повышает читаемость и поддерживаемость компонентов. Логика бизнес-процессов, взаимодействие с API, обработка событий, анимации — всё это можно вынести в контроллеры, оставив компонент тонким и декларативным. В результате проект становится более модульным, тестируемым и удобным для командной работы.
Контроллеры в FAST Element обеспечивают чистое разделение ответственности, делают компоненты гибкими, повторно используемыми и легко расширяемыми без изменения исходного шаблона.