Как заставить веб-компоненты общаться (часть 1)
Глупый веб-компонент
Для этой статьи создадим довольно бессмысленный веб-компонент <wc-highlight>
.
<wc-highlight>
<div>1</div>
<div>2</div>
<div>3</div>
</wc-highlight>
Когда веб-компонент инстанцируется, он…
- Получает всех непосредственных потомков
.children
внутри себя. - Устанавливает первый элемент в этом списке (с индексом
0
) в качестве активногоactive
. - Выделите первый элемент в коллекции, установив
[aria-selected='true']
.
customElements.define('wc-highlight', class extends HTMLElement {
/**
* Создание элемента
*/
constructor () {
// Всегда вызывайте super первым в конструкторе
super();
// Определяем свойства
this.boxes = Array.from(this.children);
this.active = 0;
// Устанавливаем [aria-selected]
// Если первый элемент, устанавливаем в true
// Иначе, устанавливаем в false
this.boxes.forEach(function (box, index) {
box.setAttribute('aria-selected', index === 0 ? true : false);
});
}
});
Также в веб-компоненте есть метод .next()
.
Он увеличивает значение this.active
на 1
(и сбрасывает его на 0
, когда достигает конц списка). Затем он обновляет атрибут [aria-selected]
, чтобы выделить новый элемент.
/**
* Перейти к следующему элементу
*/
next () {
// Кэшируем активный, в данный момент, индекс
let current = this.active;
// Обновляем активный индекс
this.active++;
// Если это конец, возвращаемся к началу.
if (this.active === this.boxes.length) {
this.active = 0;
}
// Обновляем [aria-selected]
this.boxes[current].setAttribute('aria-selected', false);
this.boxes[this.active].setAttribute('aria-selected', true);
}
Запустив его на элементе <wc-highlight>
, можно перенести выделение с текущего элемента на следующий в списке.
let highlight = document.querySelector('wc-highlight');
highlight.next();
Вкладываем веб-компонент внутрь него
Для такого простого веб-компонента я обычно использую элементы управления для перехода к следующему элементу как часть компонента.
Но в крупных проектах может быть удобно иметь ряд небольших, но взаимосвязанных компонентов, каждый из которых обрабатывает один небольшой фрагмент пользовательского интерфейса и взаимодействует с другими компонентами.
В целях обучения создадим элемент <wc-highlight-controls>
внутри constructor()
веб-компонента <wc-highlight>
и внедрим его в DOM.
/**
* Создание элемента
*/
constructor () {
// ...
this.boxes.forEach(function (box, index) {
box.setAttribute('aria-selected', index === 0 ? true : false);
});
// Append controls
let controls = document.createElement('wc-highlight-controls');
this.append(controls);
}
Затем можно определить <wc-highlight-controls>
как отдельный веб-компонент.
customElements.define('wc-highlight-controls', class extends HTMLElement {
/**
* Создание элемента
*/
constructor () {
// Всегда вызывайте super первым в конструкторе
super();
// Код компонента...
}
});
Внутри constructor()
можно использовать метод Element.closest()
, для получения родительского элемента <wc-highlight>
, и присвоить его this.highlight
.
Если родительский элемент не найден, завершаем выполнение с помощью return
.
/**
* Создание элемента
*/
constructor () {
// Всегда вызывайте super первым в конструкторе
super();
// Получаем родительский элемент <wc-highlight>
this.highlight = this.closest('wc-highlight');
if (!this.highlight) return;
Далее создадим элемент button
, зададим ему текст и .append()
его внутри веб-компонента.
Затем добавим к нему слушателя события click
.
/**
* Создание элемента
*/
constructor () {
// Всегда вызывайте super первым в конструкторе
super();
// Получаем родительский элемент <wc-highlight>
this.highlight = this.closest('wc-highlight');
if (!this.highlight) return;
// Создаём кнопку button
this.button = document.createElement('button');
this.button.textContent = 'Next';
this.append(this.button);
// Слушаем событие clicks для кнопки button
this.button.addEventListener('click', this);
}
Внутри метода handleEvent()
запускаем метод .next()
на this.highlight
, для перехода к следующему элементу.
/**
* Обработка событий
* @param {Event} event Объект события
*/
handleEvent (event) {
this.highlight.next();
}
Это очень простое подключение
Этот метод основан на тесном взаимодействии элементов DOM.
Он работает, но может быть ненадёжным, поскольку зависит от того, что определённые элементы загружаются в правильном порядке и всегда имеют доступ друг к другу.
Завтра рассмотрим предпочитаемый мною метод: Пользовательские события / Custom Events.
Они дают возможность настраивать веб-компоненты и обмениваться данными более гибким и независимым способом.
Они также позволяют разработчикам расширять веб-компонент способами, о которых при его создании вы, возможно, не подумали или не захотели их поддерживать напрямую.
Все статьи серии о Веб-Компонентах/Web Component
- Ваш первый веб-компонент
- Добавление опций в веб-компонент
- Улучшение веб-компонента
- Различные способы инстанцирования веб-компонента
- Методы жизненного цикла веб-компонента
- Как обнаружить изменение атрибутов веб-компонента
- Как заставить веб-компоненты общаться (часть 1)
- Как заставить веб-компоненты общаться (часть 2)