Синтаксис обработчиков в шаблонах

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

Привязка событий через @event

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

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

class MyButton extends FASTElement {
    count = 0;

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

MyButton.define({
    name: "my-button",
    template: html<MyButton>`
        <button @click=${x => x.increment()}>Нажато: ${x => x.count}</button>
    `
});

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

  • @click — связывает событие click с функцией increment.
  • x => x.increment() — стрелочная функция получает текущий экземпляр компонента (x) и вызывает его метод.
  • Использование ${x => x.count} обеспечивает реактивное обновление текста кнопки при изменении свойства count.

Прямое использование методов класса

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

<button @click=${x => x.handleClick()}>Клик</button>

В этом случае стрелочная функция нужна, чтобы корректно привязать контекст компонента. Простая передача @click=${this.handleClick} не гарантирует правильный this, так как шаблон работает в отдельной области.

Аргументы событий

FAST Element передаёт объект события в обработчик автоматически. Это позволяет работать с Event без дополнительных привязок:

<button @click=${(x, e) => x.onClick(e)}>Нажми меня</button>
  • x — экземпляр компонента
  • e — объект события (например, MouseEvent)
  • Метод onClick может использовать e.target, e.preventDefault() и другие стандартные свойства события.

Использование модификаторов

FAST Element поддерживает модификаторы событий, аналогичные Vue или Svelte, позволяющие управлять поведением событий прямо в шаблоне. Например, once для однократного вызова или preventDefault для предотвращения стандартного поведения:

<button @click.once=${x => x.handleClick()}>Клик один раз</button>
<form @submit.prevent=${x => x.handleSubmit()}>
    <input type="text">
    <button type="submit">Отправить</button>
</form>
  • .once гарантирует, что обработчик будет вызван только один раз.
  • .prevent предотвращает стандартное действие элемента, например, отправку формы.

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

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

class MyComponent extends FASTElement {
    onClickHand ler = () => console.log("Нажато");

    toggleHandler() {
        this.onClickHand ler = this.onClickHand ler === this.firstHandler 
            ? this.secondHandler 
            : this.firstHandler;
    }

    firstHandler() { console.log("Первый обработчик"); }
    secondHandler() { console.log("Второй обработчик"); }
}

html<MyComponent>`
    <button @click=${x => x.onClickHandler()}>Динамический клик</button>
`;

Здесь @click всегда вызывает текущую функцию, хранящуюся в свойстве onClickHandler. Изменение свойства автоматически отражается в поведении кнопки без пересоздания шаблона.

Композиция обработчиков

FAST Element позволяет комбинировать несколько обработчиков через стрелочные функции:

<button @click=${x => { x.firstAction(); x.secondAction(); }}>Комбинированный клик</button>

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

Обработка пользовательских событий

FAST Element упрощает работу с кастомными событиями. Любой компонент может генерировать события и слушать их в шаблоне:

class ChildComponent extends FASTElement {
    notify() {
        this.$emit("child-clicked", { message: "Привет" });
    }
}

html<ChildComponent>`
    <button @click=${x => x.notify()}>Отправить событие</button>
`;

Родительский компонент может подписываться на child-clicked так же, как на стандартное событие:

<child-component @child-clicked=${x => x.handleChildEvent}></child-component>
  • $emit — удобный метод для генерации пользовательских событий с передачей данных (detail).
  • Обработчик получает объект события с event.detail.

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

  • Для методов класса всегда использовать стрелочные функции в шаблоне, чтобы сохранить контекст this.
  • Если обработчик не зависит от компонента, можно использовать обычную функцию.
  • Динамическая привязка обработчиков полезна для изменения поведения без пересоздания элементов DOM.
  • Пользовательские события рекомендуется именовать через дефис (kebab-case) для совместимости с HTML.

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