Подключение контроллеров к хосту

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


Роль контроллеров

Контроллеры позволяют:

  • Управлять жизненным циклом элемента: инициализация, подключение к DOM, обновления, отключение.
  • Отделять бизнес-логику от структуры шаблона, обеспечивая чистоту кода.
  • Реализовывать повторно используемую логику, которую можно подключать к различным компонентам.

Каждый контроллер реализует интерфейс Controller, содержащий методы жизненного цикла:

class ExampleController {
    constructor(host) {
        this.host = host;
    }

    connectedCallback() {
        // Выполняется при подключении элемента к DOM
    }

    disconnectedCallback() {
        // Выполняется при удалении элемента из DOM
    }

    hostUpdated() {
        // Вызывается после обновления свойств хоста
    }
}

host — это элемент FASTElement, к которому подключен контроллер. Он предоставляет доступ к его свойствам, методам и событиям.


Подключение контроллера к элементу

Контроллеры подключаются через статическое свойство @controller или метод addController:

Через статическое свойство

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

class MyElement extends FASTElement {
    static controllers = [ExampleController];
}

В этом случае контроллер автоматически создается при инициализации элемента и получает ссылку на host.

Через метод addController

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

class MyElement extends FASTElement {
    connectedCallback() {
        super.connectedCallback();
        this.addController(new ExampleController(this));
    }
}

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


Жизненный цикл контроллера

Контроллер реагирует на события жизненного цикла элемента:

  1. Инициализация – создается экземпляр контроллера, ему передается ссылка на хост.
  2. connectedCallback – вызывается при вставке элемента в DOM. Здесь обычно подписываются события, запускаются таймеры или делаются сетевые запросы.
  3. hostUpdated – вызывается после обновления любого свойства хоста, позволяет синхронизировать внутреннее состояние контроллера с состоянием элемента.
  4. disconnectedCallback – вызывается при удалении элемента из DOM, освобождает ресурсы: удаляет слушатели событий, очищает таймеры, отменяет подписки.

Пример контроллера с полным циклом:

class TimerController {
    constructor(host) {
        this.host = host;
        this.intervalId = null;
    }

    connectedCallback() {
        this.intervalId = setInterval(() => {
            this.host.time = new Date().toLocaleTimeString();
        }, 1000);
    }

    disconnectedCallback() {
        clearInterval(this.intervalId);
    }

    hostUpdated() {
        console.log('Хост обновлен, текущее время:', this.host.time);
    }
}

Работа с событиями хоста

Контроллер может подписываться на пользовательские события элемента:

class ClickController {
    constructor(host) {
        this.host = host;
        this.onCl ick = this.onClick.bind(this);
    }

    connectedCallback() {
        this.host.addEventListener('click', this.onClick);
    }

    disconnectedCallback() {
        this.host.removeEventListener('click', this.onClick);
    }

    onClick(event) {
        console.log('Элемент кликнут', event);
    }
}

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


Доступ к свойствам и методам хоста

Контроллер может читать и изменять свойства хоста напрямую:

class CounterController {
    constructor(host) {
        this.host = host;
    }

    increment() {
        this.host.count++;
    }

    reset() {
        this.host.count = 0;
    }
}

Если свойство элемента является наблюдаемым (@observable), любые изменения будут автоматически триггерить обновления шаблона:

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

class CounterElement extends FASTElement {
    @observable count = 0;

    static controllers = [CounterController];
}

Множественные контроллеры

Элемент может иметь несколько контроллеров одновременно. Они подключаются как массив в static controllers:

class MyElement extends FASTElement {
    static controllers = [TimerController, ClickController, CounterController];
}

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


Динамическое управление контроллерами

Методы addController и removeController позволяют управлять контроллерами на лету:

const ctrl = new TimerController(myElement);
myElement.addController(ctrl);

// позже можно удалить контроллер
myElement.removeController(ctrl);

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


Резюме ключевых моментов

  • Контроллеры управляют поведением элемента и отделяют логику от шаблона.
  • Подключение возможно через static controllers или addController.
  • Методы жизненного цикла: connectedCallback, disconnectedCallback, hostUpdated.
  • Контроллеры могут работать с событиями, свойствами и методами хоста.
  • Поддерживаются множественные контроллеры и динамическое подключение/удаление.

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