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

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

В этой статье мы рассмотрим разные части веб-компонентов и способы их создания. 

Части веб-компонентов 

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

  • Пользовательский элемент — набор JavaScript API, позволяющий задавать пользовательские элементы, которые можно использовать в пользовательском интерфейсе, и их поведение.
  • Теневой DOM — набор JavaScript API для подключения инкапсулированного дерева теневого DOM элемента. Он отображается отдельно от основного DOM документа, что сохраняет приватность функций элемента, следовательно, он может выполняться без конфликтов с другими частями документа. 
  • HTML шаблоны— элементы template или slot позволяют нам писать шаблоны разметки, которые не отображаются на странице. Их можно многократно использовать как основу структуры пользовательских элементов. 

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

Чтобы создать веб-компонент, нужно сделать следующее: 

  1. Создать класс или функцию, чтобы определить функциональность веб-компонента.
  2. Зарегистрировать новый пользовательский элемент, используя метод CustomElementRegistry.define(), передающий имя элемента, который нужно определить, класс или функцию с заданной функциональностью, и, если необходимо, наследование элемента. 
  3. Прикрепить теневой DOM к пользовательскому элементу, используя метод Element.attachSHadow(). Добавить дочерние элементы, слушатели событий и т.д. в теневой DOM, используя методы обычного DOM.
  4. Задать шаблоны HTML, используя тэги template и slot. Используем стандартные методы DOM для клонирования шаблона и подключения его к нашему теневому DOM.
  5. Использовать пользовательский элемент на странице как и любой другой обычный элемент 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 и ссылаясь на внешние файлы.

 Читайте также:


Перевод статьи John Au-Yeung: Introduction to Creating Web Components

Предыдущая статьяКак работает функция Defer в Golang
Следующая статьяЛучшие практики JavaScript — производительность