Movatterモバイル変換


[0]ホーム

URL:


  1. Веб-технологии для разработчиков
  2. Интерфейсы веб API
  3. Веб-компоненты
  4. Использование пользовательских элементов

This page was translated from English by the community.Learn more and join the MDN Web Docs community.

View in EnglishAlways switch to English

Использование пользовательских элементов

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

Примечание:Пользовательские элементы поддерживаются по умолчанию в Firefox, Chrome и Opera. Safari пока поддерживает только автономные пользовательские компоненты, Edge также работает над реализацией.

Высокоуровневый обзор

Контроллером пользовательских элементов веб-документа является объектCustomElementRegistry — этот элемент позволяет регистрировать пользовательские элементы на веб-странице, возвращает информацию о зарегистрированных элементах и т.п.

Чтобы зарегистрировать пользовательский элемент на странице, используйте методCustomElementRegistry.define() method. Он принимает аргументы:

  • DOMString - имя элемента. Обратите внимание, что в именах пользовательских элементахдолжен содержаться дефис; они не могут состоять только из одного слова.
  • Объект типаclass, определяющий поведение элемента.
  • Опционально объект options, имеющий свойствоextends, соответствующее встроенному элементу, от которого наследует объект.

К примеру, мы можем определить пользовательский элементword-count element:

js
customElements.define("word-count", WordCount, { extends: "p" });

Этот элемент называетсяword-count, объект соответствующего класса называетсяWordCount, и он наследует элементу<p>.

Объект класса пользовательского элемента определяется с помощью синтаксиса классов ES 2015. Например,WordCount имеют следующую структуру:

js
class WordCount extends HTMLParagraphElement {  constructor() {    // Всегда первым делом вызывайте super() в конструкторе    super();    // Далее пишется функциональность элемента    ...  }}

Это простой пример, но его можно дополнить. Можно определить специальные lifecycle callbacks, которые будут вызваны в определённые моменты жизненного цикла элемента. Например,connectedCallback будет вызван, когда пользовательский элемент оказывается впервые встроен в DOM, аattributeChangedCallback вызывается, когда пользовательскому элементу добавляют, удаляют или изменяют какой-то атрибут.

Подробнее об этом в секцииUsing the lifecycle callbacks ниже.

Есть два типа пользовательских элементов:

  • Автономные пользовательские элементы независимы — они не наследуют встроенным HTML-элементам. Их используют на странице просто как обычный HTML-элемент. Например,<popup-info> илиdocument.createElement("popup-info").
  • Модифицированные встроенные элементы наследуют базовым HTML-элементам. Чтобы создать один из них, вы определяете элемент, от которого они унаследованы (как в примерах выше), и используете их как обычный базовый элемент, но с добавлением атрибута/свойства с именем пользовательского элементаis. Например<p is="word-count">, илиdocument.createElement("p", { is: "word-count" }).

Разбор простых примеров

А сейчас давайте разберём ещё несколько простых примеров, иллюстрирующих подробности создания пользовательских элементов.

Автономные пользовательские элементы

Рассмотрим пример автономного пользовательского элемента —<popup-info-box> (см.работающий пример). Он содержит изображение и строку, и встраивает изображение в страницу. Когда на изображение наводят фокус, компонент показывает всплывающую подсказку с текстом.

Прежде всего файл JavaScript определяет классPopUpInfo, наследующий отHTMLElement. Автономные пользовательские элементы почти всегда наследуютHTMLElement.

js
class PopUpInfo extends HTMLElement {  constructor() {    // Всегда первым делом вызывайте super() в конструкторе    super();    // далее следует функциональность элемента    ...  }}

В этом фрагменте кода содержится определение конструктораconstructor класса, которое всегда начинается с вызоваsuper() чтобы отработала цепочка прототипного наследования.

Внутри конструктора мы определяем всю функциональность, которую получит элемент при создании его объекта. В данном случае мы добавляем shadow root к пользовательскому элементу, производим манипуляции с DOM, чтобы создать определённую структуру shadow DOM внутри элемента — которая затем присоединяется к shadow root — и наконец добавляем CSS к shadow root, чтобы задать его стиль.

js
// Создание shadow rootvar shadow = this.attachShadow({ mode: "open" });// Создание spansvar wrapper = document.createElement("span");wrapper.setAttribute("class", "wrapper");var icon = document.createElement("span");icon.setAttribute("class", "icon");icon.setAttribute("tabindex", 0);var info = document.createElement("span");info.setAttribute("class", "info");// Берём содержимое атрибута и добавляем его в spanvar text = this.getAttribute("text");info.textContent = text;// Вставляем иконкуvar imgUrl;if (this.hasAttribute("img")) {  imgUrl = this.getAttribute("img");} else {  imgUrl = "img/default.png";}var img = document.createElement("img");img.src = imgUrl;icon.appendChild(img);// Создаём CSS для shadow domvar style = document.createElement("style");style.textContent =  ".wrapper {" +  // CSS truncated for brevity  // добавляем созданные элементы к shadow dom  shadow.appendChild(style);shadow.appendChild(wrapper);wrapper.appendChild(icon);wrapper.appendChild(info);

Наконец, регистрируем пользовательский элемент вCustomElementRegistry с помощью методаdefine(), который упоминался ранее — в качестве параметров мы передаём ему имя элемента и имя класса, который содержит его функциональность:

js
customElements.define("popup-info", PopUpInfo);

Теперь он доступен для использования на нашей странице. В HTML мы используем его так:

html
<popup-info  img="img/alt.png"  text="Код валидации вашей карты (CVC)  это дополнительная мера безопасности — это последние 3 или 4 цифры  на обороте вашей карты."></popup-info>

Примечание:Вы можете прочитатьполный исходный код на JavaScript здесь.

Модифицированные встроенные элементы

Теперь давайте взглянем на другой пример модифицированного пользовательского элемента —раскрывающийся список (см. действующий пример). Он превращает любой ненумерованный список в раскрывающееся/складывающееся меню.

Первым делом определим класс элемента наподобие того, как это делалось выше:

js
class ExpandingList extends HTMLUListElement {  constructor() {    // Всегда первым делом вызываем super() в конструкторе    super();    // ниже следует функциональность элемента    ...  }}

Здесь мы не будем во всех подробностях описывать функциональность элемента, вы можете понять как он работает, посмотрев исходный код. Единственное принципиальное различие с предыдущим примером состоит в том, что мы используем интерфейсHTMLUListElement, а неHTMLElement. Так что у него есть все характеристики элемента<ul>, плюс дополнительная функциональность, которую определили мы. Это и отличает модифицированный встроенный элемент от автономного пользовательского элемента.

Далее мы регистрируем этот элемент с помощью методаdefine() как в прошлом примере, только на сей раз мы добавляем объект options, который определяет, какому встроенному элементу наследует данный:

js
customElements.define("expanding-list", ExpandingList, { extends: "ul" });

Встроенный элемент используется на веб-странице немного по-другому:

html
<ul is="expanding-list">  ...</ul>

Вы задаёте элемент<ul> как обычно, но указываете имя модифицированного элемента в атрибутеis.

Примечание:Полныйисходный код на JavaScript доступен здесь.

Использование lifecycle callbacks

Вы можете определить несколько разных колбэков в конструкторе пользовательских элементов, которые сработают на разных этапах жизненного цикла элемента:

  • connectedCallback: Срабатывает, когда пользовательский элемент впервые добавляется в DOM.
  • disconnectedCallback: Срабатывает, когда пользовательский элемент удаляется из DOM.
  • adoptedCallback: Срабатывает, когда пользовательский элемент перемещён в новый документ.
  • attributeChangedCallback: Срабатывает, когда пользовательскому элементу добавляют, удаляют или изменяют атрибут.

Посмотрим на них в действии. Код ниже взят из примераlife-cycle-callbacks (см. его в действии). Это тривиальный пример, создающий на странице цветной квадрат. Вот как выглядит код пользовательского элемента:

html
<custom-square l="100" c="red"></custom-square>

Конструктор класса очень простой — мы просто добавляем shadow DOM к элементу, а затем добавляем пустые элементы<div> и<style> к shadow root:

js
var shadow = this.attachShadow({ mode: "open" });var div = document.createElement("div");var style = document.createElement("style");shadow.appendChild(style);shadow.appendChild(div);

Наиболее важная функция в этом примереupdateStyle() — она принимает элемент, находит его shadow root, находит его элемент<style>, и добавляетwidth,height, иbackground-color к стилям.

js
function updateStyle(elem) {  var shadow = elem.shadowRoot;  var childNodes = shadow.childNodes;  for (var i = 0; i < childNodes.length; i++) {    if (childNodes[i].nodeName === "STYLE") {      childNodes[i].textContent =        "div {" +        " width: " +        elem.getAttribute("l") +        "px;" +        " height: " +        elem.getAttribute("l") +        "px;" +        " background-color: " +        elem.getAttribute("c");    }  }}

Сами изменения стилей обрабатываются колбэками жизненного цикла, находящимися внутри конструктора.connectedCallback() срабатывает, когда элемент встраивается в DOM — здесь мы запускаем функциюupdateStyle() которая обеспечивает, чтобы квадрат имел стиль, описанный в его атрибутах:

js
connectedCallback() {  console.log('Пользовательский элемент квадрат добавлен на страницу.');  updateStyle(this);}

колбэкиdisconnectedCallback() иadoptedCallback() логируют простые сообщения на консоль, которые уведомляют нас, что элемент удалён из DOM или перемещён на другую страницу:

js
disconnectedCallback() {  console.log('Пользовательский элемент квадрат удален.');}adoptedCallback() {  console.log('Пользовательский элемент квадрат перемещён на другую страницу.');}

КолбэкattributeChangedCallback() запускается когда один из атрибутов элемента меняется. Как видно из его свойств, можно воздействовать на индивидуальные атрибуты, глядя на их имена, и новые и старые значения атрибутов. В данном случае, однако, мы просто снова запускаем функциюupdateStyle() чтобы убедиться, что атрибуты квадрата получили новые значения:

js
attributeChangedCallback(name, oldValue, newValue) {  console.log('Атрибуты пользовательского элемента квадрат изменились.');  updateStyle(this);}

Обратите внимание, что нужно наблюдать за атрибутами, чтобы запустить колбэкattributeChangedCallback() когда они изменятся. Это делается через вызов геттераobservedAttributes() в конструкторе, который содержит операторreturn возвращающий массив с именами атрибутов, которые вы хотите наблюдать:

js
static get observedAttributes() {return ['w', 'l']; }

В нашем случае он расположен в начале конструктора.

Примечание:Смотритеполный исходный код на JavaScript здесь.

Help improve MDN

Learn how to contribute

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp