Приложения становятся все сложнее, и нам нужен способ разделять код на управляемые фрагменты. Веб-компоненты подойдут для создания компонентов, которые можно неоднократно использовать.
Веб-компоненты также изолированы от других участков кода, следовательно, их сложно изменить из других разделов и создать конфликтующий код.
В этой статье мы рассмотрим разные части веб-компонентов и способы их создания.
Части веб-компонентов
Веб-компоненты состоят из 3 основных частей. Вместе они инкапсулируют функциональность, которую можно повторно использовать в любое время, не опасаясь конфликтов кода.
- Пользовательский элемент — набор JavaScript API, позволяющий задавать пользовательские элементы, которые можно использовать в пользовательском интерфейсе, и их поведение.
- Теневой DOM — набор JavaScript API для подключения инкапсулированного дерева теневого DOM элемента. Он отображается отдельно от основного DOM документа, что сохраняет приватность функций элемента, следовательно, он может выполняться без конфликтов с другими частями документа.
- HTML шаблоны— элементы
templateилиslotпозволяют нам писать шаблоны разметки, которые не отображаются на странице. Их можно многократно использовать как основу структуры пользовательских элементов.
Создание веб-компонентов
Чтобы создать веб-компонент, нужно сделать следующее:
- Создать класс или функцию, чтобы определить функциональность веб-компонента.
- Зарегистрировать новый пользовательский элемент, используя метод
CustomElementRegistry.define(), передающий имя элемента, который нужно определить, класс или функцию с заданной функциональностью, и, если необходимо, наследование элемента. - Прикрепить теневой DOM к пользовательскому элементу, используя метод
Element.attachSHadow(). Добавить дочерние элементы, слушатели событий и т.д. в теневой DOM, используя методы обычного DOM. - Задать шаблоны HTML, используя тэги
templateиslot. Используем стандартные методы DOM для клонирования шаблона и подключения его к нашему теневому DOM. - Использовать пользовательский элемент на странице как и любой другой обычный элемент HTML.
Базовые примеры
CustomElementRegistry хранит список определенных пользовательских элементов. Этот объект позволяет регистрировать новые пользовательские элементы на странице и возвращать информацию о зарегистрированных пользовательских элементах и т.д.
Для регистрации нового пользовательского элемента на странице используется метод CustomElementRegistry.define(). Он принимает следующие аргументы:
- Строчку, отображающую имя элемента (слова нельзя разделять пробелами, только дефисом).
- Объект класса, определяющий поведение элемента.
- Дополнительный аргумент, содержащий свойство
extends, определяющее встроенный элемент, которому наследует новый элемент (если таковой имеется).
Пользовательский элемент задается так:
class WordCount extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({
mode: 'open'
});
const span = document.createElement('span');
span.textContent = this.getAttribute('text').split(' ').length;
const style = document.createElement('style');
style.textContent = 'span { color: red }';
shadow.appendChild(style);
shadow.appendChild(span);
}
}
customElements.define('word-count', WordCount);
В коде выше мы подключили теневой DOM к документу, вызвав attachShadow . Режим mode 'open' означает, что теневой корень доступен из JavaScript вне корня. Режим также может быть 'closed' с противоположным поведением.
Затем мы создали элемент span, где задали текстовое содержимое для атрибута text length после разделения слов пробелами.
Далее создали элемент style и задали содержимое color: red.
Наконец, мы присоединили их к корню теневого DOM.
Заметьте, что в нашем классе мы расширяем HTMLElement. Это необходимо для определения пользовательского элемента.
Использовать новый элемент можно следующим образом:
<word-count text='Hello world.'></word-count>
Существуют 2 типа пользовательских элементов:
- Автономные пользовательские элементы — независимые, не наследуют от стандартных HTML элементов. Их можно создать, ссылаясь напрямую на имя. Например, написать
<word-count>илиdocument.createElement("word-count"). - Настраиваемые встроенные элементы— наследуют от базовых HTML элементов. Для создания подобных элементов расширяем один из встроенных HTML элементов, например, написав
<p is="word-count">илиdocument.createElement("p", { is: "word-count" }).
Пользовательский элемент, созданный выше — автономный. Настраиваемый элемент создается так:
class WordCount extends HTMLParagraphElement {
constructor() {
super();
const shadow = this.attachShadow({
mode: 'open'
});
const span = document.createElement('span');
span.textContent = this.getAttribute('text').split(' ').length;
const style = document.createElement('style');
style.textContent = 'span { color: red }';
shadow.appendChild(style);
shadow.appendChild(span);
}
}
customElements.define('word-count', WordCount, {
extends: 'p'
});
Чтобы поместить его на страницу, пишем:
<p is='word-count' text='Hello world.'></p>
Как видите, автономные и настраиваемые элементы не сильно отличаются друг от друга. Единственное отличие — мы расширяем HTMLParagraphElement, а не HTMLElement .
Затем используем атрибут is для ссылки на пользовательский элемент вместо использования имени элемента в настраиваемом встроенном элементе.
Внутренние или внешние стили
Мы также можем ссылаться на внешние стили вместо использования внутренних, как сделано выше. Например, напишем:
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');
shadow.appendChild(linkElem);
Мы ссылаемся на стили из style.css. Элемент link создается так же, как в HTML и нормальном DOM.
Создавать веб-компоненты просто. Нужно задать класс или функцию для определения функциональности и затем поместить их в реестр пользовательских элементов, используя метод customElements.define.
Мы можем расширить существующие элементы, такие как p, или создать новые с нуля. Также мы можем добавлять внутренние стили или ссылаться на внешние, создавая элемент link и ссылаясь на внешние файлы.
Читайте также:
- Веб-сервер с нуля в TypeScript и Node
- Лучшие практики JavaScript: переменные
- Почему мы не используем лучшие практики CI/CD
Перевод статьи John Au-Yeung: Introduction to Creating Web Components





