aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/web_components
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/web_components
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/web/web_components')
-rw-r--r--files/ru/web/web_components/html_imports/index.html37
-rw-r--r--files/ru/web/web_components/index.html205
-rw-r--r--files/ru/web/web_components/использование_пользовательских_элементов/index.html243
3 files changed, 485 insertions, 0 deletions
diff --git a/files/ru/web/web_components/html_imports/index.html b/files/ru/web/web_components/html_imports/index.html
new file mode 100644
index 0000000000..06dab35aba
--- /dev/null
+++ b/files/ru/web/web_components/html_imports/index.html
@@ -0,0 +1,37 @@
+---
+title: HTML Импорты
+slug: Web/Web_Components/HTML_Imports
+translation_of: Web/Web_Components/HTML_Imports
+---
+<div class="warning">
+<p>Firefox will not ship <em>HTML Imports</em> in its current form. See this <a href="https://hacks.mozilla.org/2015/06/the-state-of-web-components/">status update</a> for more information. Until there is a consensus on the standard or alternative mechanisms are worked out, you can use a polyfill such as Google's <code><a href="https://github.com/webcomponents/webcomponentsjs">webcomponents.js</a></code>.</p>
+</div>
+
+<p><em>HTML Импорты</em> is intended to be the packaging mechanism for <a href="/en-US/docs/Web/Web_Components">web components</a>, but you can also use HTML Imports by itself.</p>
+
+<div>You import an HTML file by using a <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a> tag in an HTML document like this: </div>
+
+<div> </div>
+
+<pre>&lt;link rel="import" href="myfile.html"&gt;</pre>
+
+<p><span style="line-height: 1.5;">The </span><code style="font-style: normal; line-height: 1.5;">import</code><span style="line-height: 1.5;"> </span><span style="line-height: 1.5;">link type </span><span style="line-height: 1.5;">is new.</span></p>
+
+<h2 id="Specification">Specification</h2>
+
+<table class="spec-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Specification</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comment</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('HTML Imports', "", "")}}</td>
+ <td>{{Spec2('HTML Imports')}}</td>
+ <td> </td>
+ </tr>
+ </tbody>
+</table>
+
+<p> </p>
diff --git a/files/ru/web/web_components/index.html b/files/ru/web/web_components/index.html
new file mode 100644
index 0000000000..e8ec0144cc
--- /dev/null
+++ b/files/ru/web/web_components/index.html
@@ -0,0 +1,205 @@
+---
+title: Веб-компоненты
+slug: Web/Web_Components
+translation_of: Web/Web_Components
+---
+<p>{{DefaultAPISidebar("Веб-компоненты")}}</p>
+
+<p>Веб-компоненты - это набор различных технологий, позволяющих создавать повторно используемые настраиваемые элементы с их функциональностью, инкапсулированной отдельно от остальной части вашего кода - и использовать их в ваших веб-приложениях.</p>
+
+<h2 id="Понятия_и_использование">Понятия и использование</h2>
+
+<p>Как разработчики, все мы знаем, что как можно больше повторного использования кода - хорошая идея. Традиционно это было не так просто для пользовательских структур разметки - подумайте о сложном HTML (и связанном с ним стиле и сценарии), которые вам иногда приходилось писать для визуализации пользовательских элементов управления UI, и о том, как их многократное использование может превратить вашу страницу в беспорядок если вы не будете осторожны.</p>
+
+<p>Веб-компоненты направлены на решение таких проблем - они состоят из трех основных технологий, которые можно использовать вместе для создания универсальных настраиваемых элементов с инкапсулированной функциональностью, которые можно повторно использовать где угодно, не опасаясь коллизий кода.</p>
+
+<ul>
+ <li><strong>Пользовательские элементы</strong>: набор API-интерфейсов JavaScript, позволяющих определять пользовательские элементы и их поведение, которые затем можно использовать по желанию в пользовательском интерфейсе.</li>
+ <li><strong>Shadow DOM</strong>: набор API-интерфейсов JavaScript для прикрепления инкапсулированного «теневого» дерева DOM к элементу, который отображается отдельно от DOM основного документа, и управления соответствующими функциями. Таким образом, вы можете сохранить функции элемента в секрете, поэтому для них можно создавать сценарии и стили, не опасаясь коллизий с другими частями документа.</li>
+ <li><strong>HTML templates</strong>: элементы {{HTMLElement("template")}} и {{HTMLElement("slot")}} позволяют создавать шаблоны разметки, которыx не видно на отображаемой странице. Затем их можно многократно использовать в качестве основы структуры настраиваемого элемента.</li>
+</ul>
+
+<p>Базовый подход к реализации веб-компонента обычно выглядит примерно так:</p>
+
+<ol>
+ <li>Создайте класс, в котором вы указываете функциональность своего веб-компонента, используя синтаксис классов ECMAScript 2015 (дополнительную информацию см. в разделе <a href="https://wiki.developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Classes">Классы</a>).</li>
+ <li>Зарегистрируйте свой новый настраиваемый элемент с помощью метода {{domxref("CustomElementRegistry.define()")}}, передав ему имя элемента, который будет определен, класс или функцию, в которых указана его функцианальность, и, необязательно, от какого элемента он наследуется.</li>
+ <li>При необходимости прикрепите теневую DOM к настраиваемому элементу с помощью метода {{domxref("Element.attachShadow()")}}. Добавьте дочерние элементы, прослушиватели событий и т.д. в теневой DOM, используя обычные методы DOM.</li>
+ <li>При необходимости определите HTML template, используя {{htmlelement("template")}} и {{htmlelement("slot")}}. Снова используйте обычные методы DOM, чтобы клонировать шаблон и прикрепить его к вашей теневой DOM.</li>
+ <li>Используйте свой настраиваемый элемент везде, где хотите, на своей странице, как и любой обычный элемент HTML.</li>
+</ol>
+
+<h2 id="Учебники">Учебники</h2>
+
+<dl>
+ <dt><a href="/ru/docs/Web/Web_Components/Using_custom_elements">Использование пользовательских элементов </a></dt>
+ <dd>Руководство, показывающее, как использовать функции настраиваемых элементов для создания простых веб-компонентов, а также рассказывает про обратные вызовы жизненного цикла и некоторые другие более сложные функции.</dd>
+ <dt><a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">Использование shadow DOM</a></dt>
+ <dd>Руководство, которое рассматривает основы теневой DOM, показывает, как прикрепить теневую DOM к элементу, добавлять к теневому дереву DOM, стилизовать его и многое другое.</dd>
+ <dt><a href="/ru/docs/Web/Web_Components/Using_templates_and_slots">Использование шаблонов и слотов</a></dt>
+ <dd>Руководство, показывающее, как определить повторно используемую структуру HTML с помощью элементов {{htmlelement("template")}} и {{htmlelement ("slot")}}, а затем использовать эту структуру внутри ваших веб-компонентов.</dd>
+</dl>
+
+<h2 id="Справка">Справка</h2>
+
+<h3 id="Пользовательские_элементы">Пользовательские элементы</h3>
+
+<dl>
+ <dt>{{domxref("CustomElementRegistry")}}</dt>
+ <dd>Содержит функции, связанные с настраиваемыми элементами, в первую очередь с методом {{domxref("CustomElementRegistry.define()")}}, используемым для регистрации новых настраиваемых элементов, чтобы их можно было затем использовать в вашем документе.</dd>
+ <dt>{{domxref("Window.customElements")}}</dt>
+ <dd>Возвращает ссылку на объект <code>CustomElementRegistry</code>.</dd>
+ <dt><a href="/ru/docs/Web/Web_Components/Using_custom_elements#Использование_lifecycle_callbacks">Обратные вызовы жизненного цикла</a></dt>
+ <dd>Специальные функции обратного вызова, определенные внутри определения класса настраиваемого элемента, которые влияют на его поведение:
+ <ul>
+ <li><code>connectedCallback</code>: вызывается, когда настраиваемый элемент впервые подключается к DOM документа.</li>
+ <li><code>disconnectedCallback</code>: вызывается, когда пользовательский элемент отключается от DOM документа.</li>
+ <li><code>adoptedCallback</code>: вызывается, когда настраиваемый элемент перемещается в новый документ.</li>
+ <li><code>attributeChangedCallback</code>: вызывается при добавлении, удалении или изменении одного из атрибутов настраиваемого элемента.</li>
+ </ul>
+ </dd>
+ <dt>Расширения для создания пользовательских встроенных элементов</dt>
+ <dd>
+ <ul>
+ <li>Глобальный атрибут HTML {{htmlattrxref("is")}}: позволяет указать, что стандартный элемент HTML должен вести себя как зарегистрированный встроенный пользовательский элемент.</li>
+ <li>Параметр «is» метода {{domxref("Document.createElement()")}}: позволяет создать экземпляр стандартного HTML-элемента, который ведет себя как заданный зарегистрированный настраиваемый встроенный элемент.</li>
+ </ul>
+ </dd>
+ <dt>Псевдоклассы CSS</dt>
+ <dd>Псевдоклассы, относящиеся конкретно к настраиваемым элементам:
+ <ul>
+ <li>{{cssxref(":defined")}}: Соответствует любому заданному элементу, включая встроенные элементы и настраиваемые элементы, определенные с помощью <code>CustomElementRegistry.define()</code>.</li>
+ <li>{{cssxref(":host")}}: Выбирает теневой хост <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">теневого DOM</a>, содержащего CSS, внутри которого он используется.</li>
+ <li>{{cssxref(":host()")}}: Выбирает теневой хост <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">теневой DOM</a>, содержащий CSS, внутри которого он используется (так что вы можете выбрать пользовательский элемент изнутри его теневой DOM) - но только если селектор, указанный в качестве параметра функции, совпадает с теневым хостом.</li>
+ <li>{{cssxref(":host-context()")}}: Выбирает теневой хост <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">теневой DOM</a>, содержащий CSS, внутри которого он используется (так что вы можете выбрать пользовательский элемент изнутри его теневой DOM) - но только если селектор, указанный в качестве параметра функции, совпадает с предком(-ами) теневого хоста в том месте, где он находится внутри иерархии DOM.</li>
+ </ul>
+ </dd>
+ <dt>Псевдоэлементы CSS</dt>
+ <dd>Псевдоэлементы, относящиеся конкретно к настраиваемым элементам:
+ <ul>
+ <li>{{cssxref("::part")}}: Представляет любой элемент в <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">теневом дереве</a>, имеющий соответствующий атрибут {{HTMLAttrxRef("part")}}.</li>
+ </ul>
+ </dd>
+</dl>
+
+<h3 id="Shadow_DOM">Shadow DOM</h3>
+
+<dl>
+ <dt>{{domxref("ShadowRoot")}}</dt>
+ <dd>Представляет корневой узел поддерева теневой модели DOM.</dd>
+ <dt>{{domxref("DocumentOrShadowRoot")}}</dt>
+ <dd>Миксин, определяющий функции, доступные для всех документов и теневых корневых узлов.</dd>
+ <dt>Расширения {{domxref("Element")}}</dt>
+ <dd>Расширения интерфейса <code>Element</code>, связанные с теневой DOM:
+ <ul>
+ <li>Метод {{domxref("Element.attachShadow()")}} прикрепляет теневое дерево DOM к указанному элементу.</li>
+ <li>Свойство {{domxref ("Element.shadowRoot")}} возвращает теневой корневой узел, прикрепленный к указанному элементу, или значение <code>null</code>, если корневой узел не прикреплен.</li>
+ </ul>
+ </dd>
+ <dt>Соответствующие дополнения {{domxref("Node")}}</dt>
+ <dd>Дополнения к интерфейсу <code>Node</code>, относящиеся к теневой DOM:
+ <ul>
+ <li>Метод {{domxref("Node.getRootNode()")}} возвращает корень объекта контекста, который необязательно включает теневой корневой узел, если он доступен.</li>
+ <li>Свойство {{domxref("Node.isConnected")}} возвращает логическое значение, указывающее, подключен ли узел (прямо или косвенно) к объекту контекста, например объект {{domxref("Document")}} в случае обычного DOM или {{domxref("ShadowRoot")}} в случае теневого DOM.</li>
+ </ul>
+ </dd>
+ <dt>Расширения {{domxref("Event")}}</dt>
+ <dd>Расширения интерфейса <code>Event</code>, относящиеся к теневой модели DOM:
+ <ul>
+ <li>{{domxref("Event.composed")}}: возвращает {{jsxref("Boolean")}}, который указывает, будет ли событие распространяться через границу теневой DOM в стандартную DOM (<code>true</code>) или нет (<code>false</code>).</li>
+ <li>{{domxref ("Event.composedPath")}}: возвращает путь к событию (объекты, для которых будут вызваны слушатели). Это не включает узлы в теневых деревьях, если теневой кореневой узел был создан с закрытым {{domxref("ShadowRoot.mode")}}.</li>
+ </ul>
+ </dd>
+</dl>
+
+<h3 id="HTML_templates">HTML templates</h3>
+
+<dl>
+ <dt>{{htmlelement("template")}}</dt>
+ <dd>Содержит фрагмент HTML, который не отображается при первоначальной загрузке содержащего документа, но может отображаться во время выполнения с помощью JavaScript, который в основном используется в качестве основы для структур настраиваемых элементов. Связанный интерфейс DOM - {{domxref("HTMLTemplateElement")}}.</dd>
+ <dt>{{htmlelement("slot")}}</dt>
+ <dd>Заполнитель внутри веб-компонента, который можно заполнить собственной разметкой, что позволяет создавать отдельные деревья DOM и представлять их вместе. Связанный интерфейс DOM - {{domxref("HTMLSlotElement")}}.</dd>
+ <dt>Глобальный HTML атрибут <code><a href="/ru/docs/Web/HTML/Global_attributes/slot">slot</a></code></dt>
+ <dd>Назначает слот элементу в теневом дереве теневого DOM.</dd>
+ <dt>{{domxref("Slotable")}}</dt>
+ <dd>Миксин, реализованный как узлами {{domxref("Element")}}, так и {{domxref("Text")}}, определяющий функции, которые позволяют им стать содержимым элемента {{htmlelement("slot")}}. Миксин определяет один атрибут, {{domxref("Slotable.assignedSlot")}}, который возвращает ссылку на слот, в который вставлен узел.</dd>
+ <dt>{{domxref("Element")}} extensions</dt>
+ <dd>Расширения интерфейса <code>Element</code>, относящиеся к слотам:
+ <ul>
+ <li>{{domxref("Element.slot")}}: Возвращает имя слота теневого DOM, прикрепленного к элементу.</li>
+ </ul>
+ </dd>
+ <dt>Псевдоэлементы CSS</dt>
+ <dd>Псевдоэлементы, относящиеся конкретно к слотам:
+ <ul>
+ <li>{{cssxref("::slotted")}}: Соответствует любому содержимому, вставленному в слот.</li>
+ </ul>
+ </dd>
+ <dt>Событие {{event("slotchange")}}</dt>
+ <dd>Вызывается для экземпляра {{domxref("HTMLSlotElement")}} (элемент {{htmlelement("slot")}}) при изменении узла(-ов), содержащихся в этом слоте.</dd>
+</dl>
+
+<h2 id="Примеры">Примеры</h2>
+
+<p>Мы создаем ряд примеров в репозитории GitHub с <a href="https://github.com/mdn/web-components-examples">примерами веб-компонентов</a>. Со временем будет добавлено больше.</p>
+
+<h2 id="Спецификации">Спецификации</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Спецификация</th>
+ <th scope="col">Статус</th>
+ <th scope="col">Комментарии</th>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML WHATWG","scripting.html#the-template-element","&lt;template&gt; element")}}</td>
+ <td>{{Spec2("HTML WHATWG")}}</td>
+ <td>Определение {{HTMLElement("template")}}.</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML WHATWG","custom-elements.html#custom-elements","custom elements")}}</td>
+ <td>{{Spec2("HTML WHATWG")}}</td>
+ <td>Определение <a href="/ru/docs/Web/Web_Components/Использование_пользовательских_элементов">пользовательских HTML элементов</a></td>
+ </tr>
+ <tr>
+ <td>{{SpecName("DOM WHATWG","#shadow-trees","shadow trees")}}</td>
+ <td>{{Spec2("DOM WHATWG")}}</td>
+ <td>Определение <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">Shadow DOM</a></td>
+ </tr>
+ <tr>
+ <td>{{SpecName("HTML Imports", "", "")}}</td>
+ <td>{{Spec2("HTML Imports")}}</td>
+ <td>Начальное определение <a href="/ru/docs/Web/Web_Components/HTML_Imports">HTML импорта</a></td>
+ </tr>
+ <tr>
+ <td>{{SpecName("Shadow DOM", "", "")}}</td>
+ <td>{{Spec2("Shadow DOM")}}</td>
+ <td>Начальное определение <a href="/ru/docs/Web/Web_Components/Using_shadow_DOM">Shadow DOM</a></td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
+
+<p>В основном:</p>
+
+<ul>
+ <li>Веб-компоненты по умолчанию поддерживаются в Firefox (версия 63), Chrome и Opera.</li>
+ <li>Safari поддерживает ряд функций веб-компонентов, но меньше, чем указанные выше браузеры.</li>
+ <li>Edge работает над реализацией.</li>
+</ul>
+
+<p>Для получения подробной информации о поддержке определенных функций браузером обратитесь к перечисленным выше справочным страницам.</p>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li><a href="https://www.webcomponents.org/">webcomponents.org</a> - сайт с примерами веб-компонентов, учебными пособиями и другой информацией.</li>
+ <li><a href="https://fast.design/" rel="noopener">FAST</a> - это библиотека веб-компонентов, созданная Microsoft, которая предлагает несколько пакетов для использования в зависимости от потребностей вашего проекта. <a href="https://github.com/microsoft/fast/tree/master/packages/web-components/fast-element" rel="noopener">Fast Element</a> - это легкое средство для простого создания производительных, эффективных с точки зрения памяти и совместимых со стандартами веб-компонентов. <a href="https://github.com/microsoft/fast/tree/master/packages/web-components/fast-foundation" rel="noopener">Fast Foundation</a> - это библиотека классов, шаблонов и других утилит веб-компонентов, построенная на основе fast-element, предназначенная для создания зарегистрированных веб-компонентов.</li>
+ <li><a href="https://github.com/hybridsjs/hybrids">Hybrids</a> - библиотека веб-компонентов с открытым исходным кодом, которая предпочитает простые объекты и чистые функции <code>class</code> и <code>this</code> синтаксису. Он предоставляет простой и функциональный API для создания пользовательских элементов.</li>
+ <li><a href="https://www.polymer-project.org/">Polymer</a> - каркас веб-компонентов Google - набор полифилов, улучшений и примеров. На данный момент самый простой способ кроссбраузерно использовать веб-компоненты.</li>
+ <li><a href="https://github.com/devpunks/snuggsi#readme">Snuggsi</a> - Простые веб-компоненты размером ~ 1 КБ, <em>включая полифил</em> - Все, что вам нужно, это браузер и базовое понимание классов HTML, CSS и JavaScript для продуктивной работы.</li>
+ <li><a href="https://github.com/slimjs/slim.js">Slim.js</a> - библиотека веб-компонентов с открытым исходным кодом - высокопроизводительная библиотека для быстрой и простой разработки компонентов; расширяемая, подключаемая и кросс-платформенная.</li>
+ <li><a href="https://stenciljs.com/">Stencil</a> - набор инструментов для создания многоразовых масштабируемых систем проектирования в веб-компонентах.</li>
+</ul>
diff --git a/files/ru/web/web_components/использование_пользовательских_элементов/index.html b/files/ru/web/web_components/использование_пользовательских_элементов/index.html
new file mode 100644
index 0000000000..bcb5b5d733
--- /dev/null
+++ b/files/ru/web/web_components/использование_пользовательских_элементов/index.html
@@ -0,0 +1,243 @@
+---
+title: Использование пользовательских элементов
+slug: Web/Web_Components/Использование_пользовательских_элементов
+translation_of: Web/Web_Components/Using_custom_elements
+---
+<div>{{DefaultAPISidebar("Web Components")}}</div>
+
+<p class="summary">Одна из ключевых особенностей стандарта Веб-компонент это возможность создавать пользовательские элементы на HTML-странице, инкапсулирующие функциональность, вместо того чтобы создавать длинyю, вложенную группу элементов, которые бы вместе реализовывали нужную пользовательскую фичу. Эта статья является вводной по использованию пользовательских HTML-компонент.</p>
+
+<div class="note">
+<p><strong>Заметка</strong>: Пользовательские элементы поддерживаются по умолчанию в Firefox, Chrome и Opera. Safari пока поддерживает только автономные пользовательские компоненты, Edge также работает над реализацией.</p>
+</div>
+
+<h2 id="Высокоуровневый_обзор">Высокоуровневый обзор</h2>
+
+<p>Контроллером пользовательских элементов веб-документа является объект {{domxref("CustomElementRegistry")}} — этот элемент позволяет регистрировать пользовательские элементы на веб-странице, возвращает информацию о зарегистрированных элементах и т.п.</p>
+
+<p>Чтобы зарегистрировать пользовательский элемент на странице, используйте метод {{domxref("CustomElementRegistry.define()")}} method. Он принимает аргументы:</p>
+
+<ul>
+ <li>{{domxref("DOMString")}} - имя элемента. Обратите внимание, что в именах пользовательских элементах <a href="https://stackoverflow.com/questions/22545621/do-custom-elements-require-a-dash-in-their-name">должен содержаться дефис</a>; они не могут состоять только из одного слова.</li>
+ <li>Объект типа <a href="/en-US/docs/Web/JavaScript/Reference/Classes">class</a>, определяющий поведение элемента.</li>
+ <li>Опционально объект options, имеющий свойство <code>extends</code>, соответствующее встроенному элементу, от которого наследует объект.</li>
+</ul>
+
+<p>К примеру, мы можем определить пользовательский элемент <a href="https://mdn.github.io/web-components-examples/word-count-web-component/">word-count element</a>:</p>
+
+<pre class="brush: js">customElements.define('word-count', WordCount, { extends: 'p' });</pre>
+
+<p>Этот элемент называется <code>word-count</code>, объект соответствующего класса называется <code>WordCount</code>, и он наследует элементу {{htmlelement("p")}}.</p>
+
+<p>Объект класса пользовательского элемента определяется с помощью синтаксиса классов ES 2015. Например, <code>WordCount</code> имеют следующую структуру:</p>
+
+<pre class="brush: js">class WordCount extends HTMLParagraphElement {
+ constructor() {
+ // Всегда первым делом вызывайте super() в конструкторе
+ super();
+
+ // Далее пишется функциональность элемента
+
+ ...
+ }
+}</pre>
+
+<p>Это простой пример, но его можно дополнить. Можно определить специальные lifecycle callbacks, которые будут вызваны в определенные моменты жизненного цикла элемента. Например, <code>connectedCallback</code> будет вызван, когда пользовательский элемент оказывается впервые встроен в DOM, а <code>attributeChangedCallback</code> вызывается, когда пользовательскому элементу добавляют, удаляют или изменяют какой-то аттрибут.</p>
+
+<p>Подробнее об этом в секции {{anch("Using the lifecycle callbacks")}} ниже.</p>
+
+<p>Есть два типа пользовательских элементов:</p>
+
+<ul>
+ <li><strong>Автономные пользователькие элементы</strong> независимы — они не наследуют встроенным HTML-элементам. Их используют на странице просто как обычный HTML-элемент. Например, <code>&lt;popup-info&gt;</code> или <code>document.createElement("popup-info")</code>.</li>
+ <li><strong>Модифицированные встроенные элементы</strong> наследуют базовым HTML-элементам. Чтобы создать один из них, вы определяете элемент, от которого они унаследованы (как в примерах выше), и используете их как обычный базовый элемент, но с добавлением атрибута/свойства с именем пользовательского элемента {{htmlattrxref("is")}}. Например <code>&lt;p is="word-count"&gt;</code>, или <code>document.createElement("p", { is: "word-count" })</code>.</li>
+</ul>
+
+<h2 id="Разбор_простых_примеров">Разбор простых примеров</h2>
+
+<p>А сейчас давайте разберем еще несколько простых примеров, иллюстрирующих подробности создания пользовательских элементов.</p>
+
+<h3 id="Автономные_пользовательские_элементы">Автономные пользовательские элементы</h3>
+
+<p>Рассмотрим пример автономного пользовательского элемента — <code><a href="https://github.com/mdn/web-components-examples/tree/master/popup-info-box-web-component">&lt;popup-info-box&gt;</a></code> (см. <a href="https://mdn.github.io/web-components-examples/popup-info-box-web-component/">работающий пример</a>). Он содержит изображение и строку, и встраивает изображение в страницу. Когда на изображение наводят фокус, компонент показывает всплывающую подсказку с текстом.</p>
+
+<p>Прежде всего файл JavaScript определяет класс <code>PopUpInfo</code>, наследующий от {{domxref("HTMLElement")}}. Автономные пользовательские элементы почти всегда наследуют <code>HTMLElement</code>.</p>
+
+<pre class="brush: js">class PopUpInfo extends HTMLElement {
+ constructor() {
+ // Всегда первым делом вызывайте super() в конструкторе
+ super();
+
+ // далее следует функциональность элемента
+
+ ...
+ }
+}</pre>
+
+<p>В этом фрагменте кода содержится определение конструктора {{jsxref("Classes.constructor","constructor")}} класса, которое всегда начинается с вызова <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super()</a></code> чтобы отработала цепочка прототипного наследования.</p>
+
+<p>Внутри конструктора мы определяем всю функциональность, которую получит элемент при создании его объекта. В данном случае мы добавляем shadow root к пользовательскому элементу, производим манипуляции с DOM, чтобы создать определенную структуру shadow DOM внутри элемента — которая затем присоединяется к shadow root — и наконец добавляем CSS к shadow root, чтобы задать его стиль.</p>
+
+<pre class="brush: js">// Создание shadow root
+var shadow = this.attachShadow({mode: 'open'});
+
+// Создание spans
+var 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');
+
+// Берем содержимое атрибута и добавляем его в span
+var 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 dom
+var 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);</pre>
+
+<p>Наконец, регистрируем пользовательский элемент в <code>CustomElementRegistry</code> с помощью метода <code>define()</code>, который упоминался ранее — в качестве параметров мы передаем ему имя элемента и имя класса, который содержит его функциональность:</p>
+
+<pre class="brush: js">customElements.define('popup-info', PopUpInfo);</pre>
+
+<p>Теперь он доступен для использования на нашей странице. В HTML мы используем его так:</p>
+
+<pre class="brush: html">&lt;popup-info img="img/alt.png" text="Код валидации вашей карты (CVC)
+ это дополнительная мера безопасности — это последние 3 или 4 цифры
+ на обороте вашей карты."&gt;</pre>
+
+<div class="note">
+<p><strong>Замечение</strong>: Вы можете прочитать <a href="https://github.com/mdn/web-components-examples/blob/master/popup-info-box-web-component/main.js">полный исходный код на JavaScript</a> здесь.</p>
+</div>
+
+<h3 id="Модифицированные_встроенные_элементы">Модифицированные встроенные элементы</h3>
+
+<p>Тепреь давайте взглянем на другой пример модифицированного пользовательского элемента — <a href="https://github.com/mdn/web-components-examples/tree/master/expanding-list-web-component">раскрывающийся список</a> (<a href="https://mdn.github.io/web-components-examples/expanding-list-web-component/">см. действующий пример</a>). Он превращает любой ненумерованный список в раскрывающееся/складывающееся меню.</p>
+
+<p>Первым делом определим класс элемента наподобие того, как это делалось выше:</p>
+
+<pre class="brush: js">class ExpandingList extends HTMLUListElement {
+ constructor() {
+ // Всегда первым делом вызываем super() в конструкторе
+ super();
+
+ // ниже следует функциональность элемента
+
+ ...
+ }
+}</pre>
+
+<p>Здесь мы не будем во всех подробностях описывать функциональность элемента, вы можете понять как он работает, посмотрев исходный код. Единственное принципиальное различие с предыдующим примером состоит в том, что мы используем интерфейс {{domxref("HTMLUListElement")}}, а не {{domxref("HTMLElement")}}. Так что у него есть все характеристики элемента {{htmlelement("ul")}}, плюс дополнительная функциональность, которую определили мы. Это и отличает модифицированный встроенный элемент от автономного пользовательского элемента.</p>
+
+<p>Далее мы регистрируем этот элемент с помощью метода <code>define()</code> как в прошлом примере, только на сей раз мы добавляем объект options, который определяет, какому встроенному элементу наследует данный:</p>
+
+<pre class="brush: js">customElements.define('expanding-list', ExpandingList, { extends: "ul" });</pre>
+
+<p>Встроенный элемент используется на веб-странице немного по-другому:</p>
+
+<pre class="brush: html">&lt;ul is="expanding-list"&gt;
+
+ ...
+
+&lt;/ul&gt;</pre>
+
+<p>Вы задаете элемент <code>&lt;ul&gt;</code> как обычно, но указываете имя модифицированного элемента в атрибуте <code>is</code>.</p>
+
+<div class="note">
+<p><strong>Замечание</strong>: Полный <a href="https://github.com/mdn/web-components-examples/blob/master/expanding-list-web-component/main.js">исходный код на JavaScript</a> доступен здесь.</p>
+</div>
+
+<h2 id="Использование_lifecycle_callbacks">Использование lifecycle callbacks</h2>
+
+<p>Вы можете определить несколько разных коллбеков в конструкторе пользовательских элементов, которые сработают на разных этапах жизненного цикла элемента:</p>
+
+<ul>
+ <li><code>connectedCallback</code>: Срабатывает, когда пользовательский элемент впервые добавляется в DOM.</li>
+ <li><code>disconnectedCallback</code>: Срабатывает, когда пользовательский элемент удаляется из DOM.</li>
+ <li><code>adoptedCallback</code>: Срабатывает, когда пользовательский элемент перемещен в новый документ.</li>
+ <li><code>attributeChangedCallback</code>: Срабатывает, когда пользовательскому элементу добавляют, удаляют или изменяют атрибут.</li>
+</ul>
+
+<p>Посмотрим на них в действии. Код ниже взят из примера <a href="https://github.com/mdn/web-components-examples/tree/master/life-cycle-callbacks">life-cycle-callbacks</a> (<a href="https://mdn.github.io/web-components-examples/life-cycle-callbacks/">см. его в действии</a>). Это тривиальный пример, создающий на странице цветной квадрат. Вот как выглядит код пользовательского элемента:</p>
+
+<pre class="brush: html">&lt;custom-square l="100" c="red"&gt;&lt;/custom-square&gt;</pre>
+
+<p>Конструктор класса очень простой — мы просто добавляем shadow DOM к элементу, а затем добавляем пустые элементы {{htmlelement("div")}} и {{htmlelement("style")}} к shadow root:</p>
+
+<pre class="brush: js">var shadow = this.attachShadow({mode: 'open'});
+
+var div = document.createElement('div');
+var style = document.createElement('style');
+shadow.appendChild(style);
+shadow.appendChild(div);</pre>
+
+<p>Наиболее важная функция в этом примере <code>updateStyle()</code> — она принимает элемент, находит его shadow root, находит его элемент <code>&lt;style&gt;</code>, и добавляет {{cssxref("width")}}, {{cssxref("height")}}, и {{cssxref("background-color")}} к стилям.</p>
+
+<pre class="brush: js">function updateStyle(elem) {
+ var shadow = elem.shadowRoot;
+ var childNodes = shadow.childNodes;
+ for(var i = 0; i &lt; 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');
+ }
+ }
+}</pre>
+
+<p>Сами изменения стилей обрабатываются коллбеками жизненного цикла, находящимися внутри конструктора. <code>connectedCallback()</code> срабатывает, когда элемент встраивается в DOM — здесь мы запускаем функцию <code>updateStyle()</code> которая обсеспечивает, чтобы квадрат имел стиль, описанный в его атрибутах:</p>
+
+<pre class="brush: js">connectedCallback() {
+ console.log('Пользовательский элемент квадрат добавлен на страницу.');
+ updateStyle(this);
+}</pre>
+
+<p>коллбеки <code>disconnectedCallback()</code> и <code>adoptedCallback()</code> логируют простые сообщения на консоль, которые уведомляют нас, что элемент удален из DOM или перемещен на другую страницу:</p>
+
+<pre class="brush: js">disconnectedCallback() {
+ console.log('Пользователский элемент квадрат удален.');
+}
+
+adoptedCallback() {
+ console.log('Пользовательский элемент квадарат перемещен на другую страницу.');
+}</pre>
+
+<p>Коллбек <code>attributeChangedCallback()</code> запускается когда один из аттрибутов элемента меняется. Как видно из его свойств, можно воздействовать на индивидуальные аттрибуты, глядя на их имена, и новые и старые значения аттрибутов. В данном случае, однако, мы просто снова запускаем функцию <code>updateStyle()</code> чтобы убедиться, что атрибуты квадрата получили новые значения:</p>
+
+<pre class="brush: js">attributeChangedCallback(name, oldValue, newValue) {
+ console.log('Атрибуты пользовательского элемента квадрат изменились.');
+ updateStyle(this);
+}</pre>
+
+<p>Обратите внимание, что нужно наблюдать за атрибутами, чтобы запустить коллбек <code>attributeChangedCallback()</code> когда они изменятся. Это делается через вызов геттера <code>observedAttributes()</code> в конструкторе, который содержит оператор <code>return</code> возвращающий массив с именами атрибутов, которые вы хотите наблюдать:</p>
+
+<pre class="brush: js">static get observedAttributes() {return ['w', 'l']; }</pre>
+
+<p>В нашем случае он расположен в начале конструктора.</p>
+
+<div class="note">
+<p><strong>Замечение</strong>: Смотрите <a href="https://github.com/mdn/web-components-examples/blob/master/life-cycle-callbacks/main.js">полный исходный код на JavaScript</a> здесь.</p>
+</div>