Делегирование событий

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

Основные принципы

  1. Обработчик ставится на родительский элемент, который существует в DOM на момент привязки.
  2. Цель события определяется внутри обработчика через event.target или методы closest.
  3. Фильтрация событий позволяет реагировать только на нужные элементы, игнорируя остальные.
import { FASTElement, html, css } from "@microsoft/fast-element";

class MyList extends FASTElement {
  items = ["Первый", "Второй", "Третий"];

  handleClick(event) {
    const button = event.target.closest("button");
    if (!button) return;

    const index = button.dataset.index;
    console.log(`Нажата кнопка с индексом ${index}`);
  }
}

MyList.define({
  name: "my-list",
  template: html<MyList>`
    <ul @click="${x => x.handleClick($event)}">
      ${x => x.items.map((item, index) => html`
        <li>
          ${item} <button data-index="${index}">Клик</button>
        </li>
      `)}
    </ul>
  `
});

Ключевые моменты:

  • Обработчик handleClick привязан к <ul>, а не к каждой кнопке.
  • Используется closest("button") для фильтрации событий, приходящих от дочерних элементов.
  • Атрибут data-index передает контекст элемента, что позволяет идентифицировать источник события.

Преимущества делегирования в FAST Element

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

Использование @event с фильтрацией

FAST Element поддерживает синтаксис @event="handler" с дополнительными возможностями фильтрации:

<ul @click="${x => x.handleClick($event)}">

Для более сложной фильтрации можно использовать собственные директивы или встроенные методы, например matches:

handleClick(event) {
  if (!event.target.matches("button.delete")) return;

  console.log("Удаление элемента");
}

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

Делегирование и шаблоны FAST

FAST Element активно использует шаблоны и привязку данных. Делегирование идеально сочетается с повторяющимися элементами:

html<MyList>`
  <ul @click="${x => x.handleClick($event)}">
    ${x => x.items.map((item, index) => html`
      <li>
        <span>${item}</span>
        <button class="edit" data-index="${index}">Редактировать</button>
        <button class="delete" data-index="${index}">Удалить</button>
      </li>
    `)}
  </ul>
`

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

Практические советы

  • Использовать closest вместо прямого сравнения event.target, чтобы корректно обрабатывать вложенные элементы.
  • Не навешивать обработчики на каждый элемент при повторяющихся списках — это снижает производительность.
  • Применять фильтры по классу или атрибуту для обработки разных типов событий через один родительский обработчик.
  • Сохранять данные о контексте в data-* атрибутах или через привязку шаблона, чтобы обработчик имел всю необходимую информацию.

Делегирование на пользовательских компонентах

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

class CardComponent extends FASTElement {
  handleAction(event) {
    const actionButton = event.target.closest("button.action");
    if (!actionButton) return;

    const type = actionButton.dataset.type;
    console.log(`Действие: ${type}`);
  }
}

CardComponent.define({
  name: "card-component",
  template: html<CardComponent>`
    <div @click="${x => x.handleAction($event)}">
      <button class="action" data-type="like">Лайк</button>
      <button class="action" data-type="share">Поделиться</button>
    </div>
  `
});

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


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