Обработка событий

Polymer предоставляет мощный и гибкий механизм работы с событиями, который позволяет управлять взаимодействием компонентов и DOM на современном уровне. В основе лежит стандартная модель событий веб-платформы, расширенная возможностями декларативного связывания и шаблонного синтаксиса.

События в Custom Elements

Любой компонент Polymer является расширением стандартного HTMLElement. Это означает, что можно использовать стандартные методы для работы с событиями:

this.addEventListener('click', this._handleClick);
this.removeEventListener('click', this._handleClick);

Однако Polymer добавляет удобство через декларативное связывание событий прямо в шаблоне:

<template>
  <button on-click="handleClick">Нажми меня</button>
</template>

Здесь on-click="handleClick" автоматически привязывает метод handleClick класса к событию click. Такой подход исключает необходимость ручного добавления и удаления слушателей в коде.

Пользовательские события

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

this.dispatchEvent(new CustomEvent('my-event', {
  detail: { value: 42 },
  bubbles: true,
  composed: true
}));

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

  • detail содержит данные, передаваемые вместе с событием.
  • bubbles: true позволяет событию всплывать вверх по дереву DOM.
  • composed: true делает событие видимым за пределами Shadow DOM, что важно для компонентов с инкапсуляцией.

Обработчик такого события можно указать как в родительском элементе, так и через декларативное связывание:

<my-element on-my-event="handleMyEvent"></my-element>
handleMyEvent(e) {
  console.log(e.detail.value); // 42
}

Методы для упрощения работы с событиями

Polymer предоставляет несколько утилит для работы с событиями внутри компонентов:

  • fire(eventName, detail, options) — упрощает создание и диспатчинг пользовательских событий:
this.fire('item-selected', { id: 123 });
  • listen(node, eventName, methodName) и unlisten(node, eventName, methodName) — позволяют программно управлять слушателями событий на сторонних элементах.

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

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

Делегирование событий особенно полезно для динамически создаваемых элементов внутри шаблона. Polymer поддерживает делегирование через on- атрибуты с CSS-селекторами:

<template>
  <div id="container">
    <template is="dom-repeat" items="{{items}}">
      <button on-click="handleItemClick">{{item.name}}</button>
    </template>
  </div>
</template>

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

Особенности работы со Shadow DOM

Polymer активно использует Shadow DOM для инкапсуляции стилей и структуры компонента. При работе с событиями это накладывает несколько правил:

  • События, инициированные внутри Shadow DOM, по умолчанию не видны снаружи.
  • Для внешних компонентов важно использовать composed: true при создании CustomEvent.
  • Стандартные события (например, click) автоматически всплывают через Shadow DOM, что позволяет применять привычное делегирование.

Асинхронные события

Для управления асинхронными событиями и взаимодействия компонентов можно использовать методы async и setTimeout в сочетании с диспатчингом событий:

this.async(() => {
  this.fire('data-loaded', { items: this.items });
}, 0);

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

Практика: комбинированные события

Частой задачей является необходимость комбинировать несколько событий или реагировать на последовательность действий пользователя. Polymer позволяет легко создавать цепочки событий:

handleInputChange(e) {
  this._value = e.target.value;
  this.fire('value-changed', { value: this._value });
}

handleValueChanged(e) {
  console.log('Новое значение:', e.detail.value);
}

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

Итоговые рекомендации по обработке событий

  • Использовать декларативное связывание on-event для упрощения кода.
  • Пользовательские события создавать через fire или dispatchEvent с bubbles и composed.
  • Делегировать события для динамических элементов через dom-repeat.
  • Асинхронные события диспатчить через async для корректного взаимодействия с DOM.
  • При работе с Shadow DOM учитывать область видимости событий.

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