@Listen для обработки событий

В Stencil, как и в других фреймворках, важно эффективно управлять событиями, происходящими в приложении. Одним из способов обработки событий является использование декоратора @Listen, который позволяет подписаться на события, происходящие на уровне компонента или в его дочерних элементах.

Что такое декоратор @Listen

Декоратор @Listen позволяет компоненту Stencil прослушивать события, генерируемые в DOM, и реагировать на них. С помощью этого механизма можно обработать не только нативные события браузера, но и кастомные события, которые создаются в других компонентах. Используя @Listen, можно избежать явного добавления обработчиков событий через методы DOM API (например, addEventListener), что делает код более декларативным и упрощает управление.

Синтаксис использования

Декоратор @Listen применяется к методу компонента. С его помощью указывается, на какое событие нужно подписаться и какой метод должен быть вызван при его срабатывании.

Пример использования:

import { Component, Listen } from '@stencil/core';

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {

  @Listen('click')
  handleClick(event: Event) {
    console.log('Клик на компоненте', event);
  }

}

В этом примере метод handleClick будет вызываться каждый раз, когда на элементе my-component будет сгенерировано событие click.

Слушание событий на родительских компонентах и глобальных событиях

С помощью @Listen можно подписываться на события, происходящие не только внутри компонента, но и на его родителе или в глобальном контексте. Для этого нужно указать элемент или документ, на котором должно быть обработано событие.

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

@Listen('click', { target: 'parent' })
handleParentClick(event: Event) {
  console.log('Клик на родительском элементе', event);
}

Здесь событие будет слушаться на родительском элементе компонента.

Пример прослушивания глобального события:

@Listen('resize', { target: 'window' })
handleWindowResize(event: Event) {
  console.log('Изменение размера окна', event);
}

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

Дополнительные параметры декоратора

Декоратор @Listen имеет несколько параметров, которые позволяют настроить поведение обработчика событий:

  1. target: указывает на какой объект будет подписываться событие. Это может быть один из следующих вариантов:

    • window: событие прослушивается на объекте окна.
    • document: событие прослушивается на объекте документа.
    • parent: событие прослушивается на родительском элементе компонента.
    • body: событие прослушивается на теле документа.
    • self: событие прослушивается на самом компоненте (по умолчанию).
  2. capture: если установлено в true, событие будет перехвачено на стадии захвата, а не на стадии всплытия.

Пример с дополнительными параметрами:

@Listen('scroll', { target: 'window', capture: true })
handleWindowScroll(event: Event) {
  console.log('Прокрутка окна', event);
}

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

Условное прослушивание событий

С помощью декоратора @Listen можно подписываться на события только при определенных условиях. Например, можно указать, что событие должно срабатывать только в случае выполнения определенной логики. Для этого можно использовать параметры once и passive, а также проверку в методе обработчика.

  1. once: если установлено в true, обработчик будет вызван только один раз, после чего автоматически удалится.
  2. passive: если установлено в true, это сигнализирует браузеру, что обработчик события не будет вызывать preventDefault(), что может улучшить производительность.

Пример:

@Listen('touchstart', { once: true, passive: true })
handleTouchStart(event: Event) {
  console.log('Тап по экрану (один раз)', event);
}

Обработка событий с параметрами

Метод, к которому применен декоратор @Listen, может принимать параметры события. В Stencil, в отличие от других фреймворков, это не всегда происходит автоматически. Чтобы получить доступ к данным события, необходимо явно указать параметр в методе.

@Listen('click')
handleClick(event: MouseEvent) {
  console.log('Клик мышью на элементе', event.clientX, event.clientY);
}

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

Остановка всплытия и отмена действия события

Как и при работе с нативными обработчиками событий, в Stencil можно использовать методы event.stopPropagation() и event.preventDefault() для контроля поведения события.

@Listen('click')
handleClick(event: MouseEvent) {
  event.stopPropagation();
  console.log('Всплытие события остановлено');
}

В этом примере событие будет остановлено на текущем элементе и не будет продолжать всплывать.

Пример: Слушаем кастомные события

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

Пример создания и обработки кастомного события:

import { Component, EventEmitter, Event, Listen } from '@stencil/core';

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true
})
export class MyComponent {

  @Event() customEvent: EventEmitter;

  triggerCustomEvent() {
    this.customEvent.emit();
  }

  @Listen('customEvent')
  handleCustomEvent(event: CustomEvent) {
    console.log('Кастомное событие обработано', event);
  }

}

В этом примере метод handleCustomEvent будет вызываться при срабатывании кастомного события customEvent.

Заключение

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