Как заставить веб-компоненты общаться (часть 2)

Источник: «How to get different Web Components to talk to each other (part 2)»
Вчера мы узнали, как связать дочерний и родительский веб-компонент. Сегодня рассмотрим, как использовать пользовательские события Custom Event.

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

Метод new CustomEvent() создаёт объект пользовательского события, которое можно инициировать на определённом элементе.

Передайте тип события в качестве аргумента. В качестве второго аргумента можно указать объект, содержащий подробную информацию о том, является ли событие bubbles (распространяемым), cancelable (отменяемым), и любые detail (детали), которыми хотите поделиться.

Затем запускаете метод dispatchEvent() на элементе, передавая событие в качестве аргумента.

// Создаём новое событие
let event = new CustomEvent(`my-event`, {
bubbles: true,
cancelable: true,
detail: 'Hi there!'
});

// Передаём событие
let elem = document.querySelector('#app');
elem.dispatchEvent(event);

Затем можно прослушать это событие с помощью метода Element.addEventListner(), как и любое другое событие.

elem.addEventListener('my-event', function (event) {
console.log(event.detail);
});

Существует множество различных соглашений об именовании, но для библиотечных событий я предпочитаю использовать шаблон {library-name}:{event-type}.

Например, я назову событие, возникающее при нажатии кнопки Next в веб-компоненте <wc-highlight-controls>highlight-controls:next.

Создание события веб-компонента

Давайте заменим в веб-компоненте <wc-highlight-controls> this.highlight.next() в методе handleEvent() на пользовательское событие.

/**
* Обработка событий
* @param {Event} event Объект события
*/

handleEvent (event) {

// Создаём новое событие
let next = new CustomEvent('highlight-controls:next', {
bubbles: true
});

// Отправляем событие
this.dispatchEvent(next);

}

Также можно удалить this.highlight из constructor(), поскольку он больше не нужен.

Вернувшись в веб-компонент <wc-highlight>, можно прослушивать событие highlight-controls:next внутри constructor(). Благодаря тому, что события распространяются, можно прослушивать непосредственно наш элемент и перехватывать любые события, происходящие в нем.

/**
* Создание элемента
*/

constructor () {

// ...

// Добавляем controls
let controls = document.createElement('wc-highlight-controls');
this.append(controls);

// Слушаем событие highlight-controls:next
this.addEventListener('highlight-controls:next', this);

}

Затем обработаем событие, выполнив this.next().

/**
* Обработка событий
* @param {Event} event Объект события
*/

handleEvent (event) {
this.next();
}

See the Pen

Щедро используйте события

Если бы я создавал это как реальный веб-компонент, я бы, вероятно, эмитировал событие highlight:next внутри метода .next() для веб-компонента <wc-highlight>.

Я бы включил в details свойства current и this.active, а также количество всех блоков. Это событие может быть использовано другими веб-компонентами, которые может создать разработчик.

/**
* Перейти к следующему элементу
*/

next () {

// ...

// Обновляем [aria-selected]
this.boxes[current].setAttribute('aria-selected', false);
this.boxes[this.active].setAttribute('aria-selected', true);

// Создаём новое событие
let next = new CustomEvent('highlight:next', {
bubbles: true,
detail: {
current,
next: this.active,
boxes: this.boxes
}
});

// Отправляем событие
this.dispatchEvent(next);

}

Например, это можно использовать для создания дополнительного пользовательского интерфейса, отображающего номер текущего выделенного блока, например 1 из 3.

Все статьи серии о Веб-Компонентах/Web Component

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

Предыдущая Статья

Как заставить веб-компоненты общаться (часть 1)

Следующая Статья

Как исключить middleware в определённых роутах Laravel