Использование только базового API веб-компонентов
Веб-компоненты - это набор низкоуровневых характеристик браузера, которые позволяют нам писать инкапсулированные, модульные и повторно используемые элементы HTML.
Веб-компоненты работают в любой стандартной веб-среде, которая поддерживает базовый HTML и JavaScript, и мы можем повторно использовать их в приложениях. которые мы построили с использованием разных технологий.
Чтобы следовать этому руководству, вы можете использовать онлайн-редактор кода, например jsbin, и желательно иметь базовые знания о:
- HTML, CSS и Javascript.
- Модули Javascript
- Стрелочные функции
Основные особенности веб-компонентов:
- Пользовательские элементы
- Шаблоны
- Теневой DOM
Мы собираемся создавать наш пользовательский компонент ‹my-component› шаг за шагом.
<my-component> <h1>Hello world!</h1> </my-component>
В настоящее время ваш браузер не поддерживает тег ‹my-component›. Когда браузер находит неизвестный HTML-тег, например ‹my-component›, он отображает его как встроенный элемент и продолжает визуализацию следующих элементов. Используя API пользовательских элементов, мы можем сообщить браузеру, что делать с нашим новым тегом HTML.
Давайте добавим тег скрипта внизу нашего элемента ‹body›:
<!DOCTYPE html> <html> <body> <h1>Hello world!</h1> <script> /*the code of our component go here. */ </script> </body> </html>
Чтобы создать собственный элемент, мы собираемся создать класс, расширяющий класс HTMLElement. Этот класс является базовым для всех остальных собственных элементов HTML, таких как элемент ‹input›.
class MyComponent extends HTMLElement{ connectedCallback() { console.log('my component is connected!'); } }
После создания нашего класса мы можем связать его с именем тега, определив его в реестре настраиваемых элементов.
customElements.define('my-component', MyComponent);
Когда браузер создает экземпляр нашего настраиваемого тега, он запускает некоторые обратные вызовы жизненного цикла. Для простоты единственными методами жизненного цикла, которые мы увидим, являются ‹connectedCallback ()› и ‹disconnectedCallback ()›, как мы можем видеть ниже:
class MyComponent extends HTMLElement{ constructor() { super(); /*called when the class is instantiated */ } connectedCallback() { /*called when the element is connected to the page. This can be called multiple times during the element's lifecycle. for example when using drag&drop to move elements around */ } disconnectedCallback() { /*called when the element is disconnected from the page */ }
Поскольку наш класс расширяется от класса HTMLElement, при его создании экземпляр класса является фактическим живым элементом DOM. Обратите внимание, что здесь также существуют все методы и свойства из обычного элемента DOM.
class MyComponent extends HTMLElement{ connectedCallback() { this.style.color = 'red'; } }
Чтобы ответить на ввод пользователя, мы можем добавить прослушиватель событий к нашему элементу или одному из его дочерних элементов. Давайте добавим тот, который меняет цвет элемента при нажатии:
class MyComponent extends HTMLElement{ constructor() { super(); this.addEventListener('click', () => { this.style.color === 'red' ? this.style.color = 'blue': this.style.color = 'red'; }); } connectedCallback() { this.style.color = 'blue'; } }
Результирующий код:
<!DOCTYPE html> <html> <body> <my-component> <h1>Hello Rick!</h1> </my-component> <script> class MyComponent extends HTMLElement { constructor() { super(); this.addEventListener('click', () => { this.style.color === 'red' ? this.style.color = 'blue': this.style.color = 'red'; }); } connectedCallback() { /*called when the element is connected to the page */ this.style.color = 'blue'; } } customElements.define('my-component', MyComponent); </script> </body> </html>
С веб-компонентами мы обычно хотим делать больше, чем просто устанавливать некоторые стили. Обычно нам нужно визуализировать больше частей нашего компонента и обновлять его части, когда пользователь взаимодействует с ним.
Браузер предоставляет нам элемент ‹template›, чтобы сделать это эффективно. Этот элемент позволяет нам заранее задать структуру части HTML и при необходимости эффективно клонировать ее. Сделать это быстрее, чем каждый раз воссоздавать одну и ту же структуру HTML.
Давайте создадим ‹template› внутри тегов body:
<template> <h1>Hello Rick!</h1> </template>
Как мы видим, «Привет, Рик!» больше не отображается на странице, потому что внутри нее ничего не отображается и не выполняется.
Теперь мы можем восстановить и использовать шаблон. Мы клонируем его содержимое, выполняя импорт и добавляя клонированный элемент к дочерним элементам компонента.
Результирующий код:
<!DOCTYPE html> <html> <body> <template> <h1>Hello Rick!</h1> </template> <my-component></my-component> <script> class MyComponent extends HTMLElement { constructor() { super(); this.addEventListener('click', () => { this.style.color === 'red' ? this.style.color = 'blue': this.style.color = 'red'; }); } connectedCallback() { /*called when the element is connected to the page */ this.style.color = 'blue'; const template = document. querySelector('template'); const clone = document. importNode(template.content, true); this.appendChild(clone); } } customElements.define('my-component', MyComponent); </script> </body> </html>
Веб-компоненты дают нам возможность использовать «ShadowDOM», эта функция теперь встроена в браузер, поэтому, если мы добавим дочерние элементы в Shadow DOM компонента, они не будут дочерними элементами наш элемент. Тем не менее, вместо этого они будут заключены в теневой корень.
Этот теневой корень - это особый тип узла DOM, который инкапсулирует элементы внутри себя. Стили, скрипты и другие элементы, определенные внутри этого теневого корня, не просачиваются, и наоборот, поэтому мы добиваемся инкапсуляции.
Благодаря теневому корню у нас есть гарантия, что наши компоненты всегда работают одинаково, независимо от среды, и, следовательно, мы можем создавать повторно используемые компоненты.
Для использования теневого корня в нашем компоненте замените строку: this.appendChild (clone) на this.attachShadow ({mode: ‘open’}) и this.shadowRoot.appendChild (клон):
Окончательный результирующий код:
<!DOCTYPE html> <html> <body> <template> <h1>Hello Rick!</h1> </template> <my-component></my-component> <script> class MyComponent extends HTMLElement { constructor() { super(); this.addEventListener('click', () => { this.style.color === 'red' ? this.style.color = 'blue': this.style.color = 'red'; }); } connectedCallback() { /*called when the element is connected to the page */ this.style.color = 'blue'; const template = document.querySelector('template'); const clone = document. importNode(template.content, true); //this.appendChild(clone); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(clone); } } customElements.define('my-component', MyComponent); </script> </body> </html>
Заключение
Здесь мы увидели, как создать базовый веб-компонент с использованием ванильного JavaScript. Вы можете писать веб-компоненты, используя только базовые API веб-компонентов. Использование базового API может быть хорошим выбором, если вы хотите, чтобы зависимости были низкими. В противном случае рекомендуется использовать облегченные библиотеки, чтобы повысить удобство разработки и уменьшить количество шаблонов.
Примечание от JavaScript In Plain English: Мы всегда заинтересованы в содействии продвижению качественного контента. Если у вас есть статья, которую вы хотите отправить в JavaScript In Plain English, отправьте нам электронное письмо по адресу [email protected] с вашим именем пользователя Medium, и мы добавим вас в качестве автора.