Web components что это
Перейти к содержимому

Web components что это

  • автор:

Веб-компоненты

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

Понятия и использование

Как разработчики, все мы знаем, что как можно больше повторного использования кода — хорошая идея. Традиционно это было не так просто для пользовательских структур разметки — подумайте о сложном HTML (и связанном с ним стиле и сценарии), которые вам иногда приходилось писать для визуализации пользовательских элементов управления UI, и о том, как их многократное использование может превратить вашу страницу в беспорядок если вы не будете осторожны.

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

  • Пользовательские элементы: набор API-интерфейсов JavaScript, позволяющих определять пользовательские элементы и их поведение, которые затем можно использовать по желанию в пользовательском интерфейсе.
  • Shadow DOM: набор API-интерфейсов JavaScript для прикрепления инкапсулированного «теневого» дерева DOM к элементу, который отображается отдельно от DOM основного документа, и управления соответствующими функциями. Таким образом, вы можете сохранить функции элемента в секрете, поэтому для них можно создавать сценарии и стили, не опасаясь коллизий с другими частями документа.
  • HTML templates: элементы и позволяют создавать шаблоны разметки, которых не видно на отображаемой странице. Затем их можно многократно использовать в качестве основы структуры настраиваемого элемента.

Базовый подход к реализации веб-компонента обычно выглядит примерно так:

  1. Создайте класс, в котором вы указываете функциональность своего веб-компонента, используя синтаксис классов ECMAScript 2015 (дополнительную информацию см. в разделе Классы).
  2. Зарегистрируйте свой новый настраиваемый элемент с помощью метода CustomElementRegistry.define() , передав ему имя элемента, который будет определён, класс или функцию, в которых указана его функциональность, и, необязательно, от какого элемента он наследуется.
  3. При необходимости прикрепите теневую DOM к настраиваемому элементу с помощью метода Element.attachShadow() . Добавьте дочерние элементы, обработчики событий и т.д. в теневой DOM, используя обычные методы DOM.
  4. При необходимости определите HTML template, используя и . Снова используйте обычные методы DOM, чтобы клонировать шаблон и прикрепить его к вашей теневой DOM.
  5. Используйте свой настраиваемый элемент везде, где хотите, на своей странице, как и любой обычный элемент HTML.

Учебники

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

Руководство, которое рассматривает основы теневой DOM, показывает, как прикрепить теневую DOM к элементу, добавлять к теневому дереву DOM, стилизовать его и многое другое.

Руководство, показывающее, как определить повторно используемую структуру HTML с помощью элементов и , а затем использовать эту структуру внутри ваших веб-компонентов.

Справка

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

Содержит функции, связанные с настраиваемыми элементами, в первую очередь с методом CustomElementRegistry.define() , используемым для регистрации новых настраиваемых элементов, чтобы их можно было затем использовать в вашем документе.

Возвращает ссылку на объект CustomElementRegistry .

Специальные колбэк-функции, определённые внутри определения класса настраиваемого элемента, которые влияют на его поведение:

  • connectedCallback : вызывается, когда настраиваемый элемент впервые подключается к DOM документа.
  • disconnectedCallback : вызывается, когда пользовательский элемент отключается от DOM документа.
  • adoptedCallback : вызывается, когда настраиваемый элемент перемещается в новый документ.
  • attributeChangedCallback : вызывается при добавлении, удалении или изменении одного из атрибутов настраиваемого элемента.
  • Глобальный атрибут HTML is : позволяет указать, что стандартный элемент HTML должен вести себя как зарегистрированный встроенный пользовательский элемент.
  • Параметр «is» метода Document.createElement() : позволяет создать экземпляр стандартного HTML-элемента, который ведёт себя как заданный зарегистрированный настраиваемый встроенный элемент.

Псевдоклассы, относящиеся конкретно к настраиваемым элементам:

  • :defined : Соответствует любому заданному элементу, включая встроенные элементы и настраиваемые элементы, определённые с помощью CustomElementRegistry.define() .
  • :host (en-US): Выбирает теневой хост теневого DOM (en-US), содержащего CSS, внутри которого он используется.
  • :host() : Выбирает теневой хост теневой DOM (en-US), содержащий CSS, внутри которого он используется (так что вы можете выбрать пользовательский элемент изнутри его теневой DOM) — но только если селектор, указанный в качестве параметра функции, совпадает с теневым хостом.
  • :host-context() : Выбирает теневой хост теневой DOM (en-US), содержащий CSS, внутри которого он используется (так что вы можете выбрать пользовательский элемент изнутри его теневой DOM) — но только если селектор, указанный в качестве параметра функции, совпадает с предком(-ами) теневого хоста в том месте, где он находится внутри иерархии DOM.

Псевдоэлементы, относящиеся конкретно к настраиваемым элементам:

  • ::part (en-US): Представляет любой элемент в теневом дереве (en-US), имеющий соответствующий атрибут part .

Shadow DOM

Представляет корневой узел поддерева теневой модели DOM.

Миксин, определяющий функции, доступные для всех документов и теневых корневых узлов.

Расширения интерфейса Element , связанные с теневой DOM:

  • Метод Element.attachShadow() прикрепляет теневое дерево DOM к указанному элементу.
  • Свойство Element.shadowRoot возвращает теневой корневой узел, прикреплённый к указанному элементу, или значение null , если корневой узел не прикреплён.

Дополнения к интерфейсу Node , относящиеся к теневой DOM:

  • Метод Node.getRootNode() (en-US) возвращает корень объекта контекста, который необязательно включает теневой корневой узел, если он доступен.
  • Свойство Node.isConnected возвращает логическое значение, указывающее, подключён ли узел (прямо или косвенно) к объекту контекста, например объект Document в случае обычного DOM или ShadowRoot (en-US) в случае теневого DOM.

Расширения интерфейса Event , относящиеся к теневой модели DOM:

  • Event.composed (en-US): возвращает Boolean , который указывает, будет ли событие распространяться через границу теневой DOM в стандартную DOM ( true ) или нет ( false ).
  • Event.composedPath (en-US): возвращает путь к событию (объекты, для которых будут вызваны обработчики). Это не включает узлы в теневых деревьях, если теневой корневой узел был создан с закрытым ShadowRoot.mode (en-US).

HTML templates

Содержит фрагмент HTML, который не отображается при первоначальной загрузке содержащего документа, но может отображаться во время выполнения с помощью JavaScript, который в основном используется в качестве основы для структур настраиваемых элементов. Связанный интерфейс DOM — HTMLTemplateElement (en-US).

Заполнитель внутри веб-компонента, который можно заполнить собственной разметкой, что позволяет создавать отдельные деревья DOM и представлять их вместе. Связанный интерфейс DOM — HTMLSlotElement .

Назначает слот элементу в теневом дереве теневого DOM.

Миксин, реализованный как узлами Element , так и Text , определяющий функции, которые позволяют им стать содержимым элемента . Миксин определяет один атрибут, Slotable.assignedSlot (en-US), который возвращает ссылку на слот, в который вставлен узел.

Расширения интерфейса Element , относящиеся к слотам:

  • Element.slot : Возвращает имя слота теневого DOM, прикреплённого к элементу.

Псевдоэлементы, относящиеся конкретно к слотам:

  • ::slotted : Соответствует любому содержимому, вставленному в слот.

Примеры

Мы создаём ряд примеров в репозитории GitHub с примерами веб-компонентов. Со временем будет добавлено больше.

Спецификации

Specification
HTML Standard
# the-template-element
DOM Standard
# interface-shadowroot

Совместимость с браузерами

html.elements.template

BCD tables only load in the browser

api.ShadowRoot

BCD tables only load in the browser

Смотрите также

  • webcomponents.org — сайт с примерами веб-компонентов, учебными пособиями и другой информацией.
  • FAST — это библиотека веб-компонентов, созданная Microsoft, которая предлагает несколько пакетов для использования в зависимости от потребностей вашего проекта. Fast Element — это лёгкое средство для простого создания производительных, эффективных с точки зрения памяти и совместимых со стандартами веб-компонентов. Fast Foundation — это библиотека классов, шаблонов и других утилит веб-компонентов, построенная на основе fast-element, предназначенная для создания зарегистрированных веб-компонентов.
  • Hybrids — библиотека веб-компонентов с открытым исходным кодом, которая предпочитает простые объекты и чистые функции class и this синтаксису. Он предоставляет простой и функциональный API для создания пользовательских элементов.
  • Polymer — каркас веб-компонентов Google — набор полифилов, улучшений и примеров. На данный момент самый простой способ кроссбраузерно использовать веб-компоненты.
  • Snuggsi — Простые веб-компоненты размером ~ 1 КБ, включая полифил — Все, что вам нужно, это браузер и базовое понимание классов HTML, CSS и JavaScript для продуктивной работы.
  • Slim.js — библиотека веб-компонентов с открытым исходным кодом — высокопроизводительная библиотека для быстрой и простой разработки компонентов; расширяемая, подключаемая и кросс-платформенная.
  • Stencil — набор инструментов для создания многоразовых масштабируемых систем проектирования в веб-компонентах.

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 3 авг. 2023 г. by MDN contributors.

Your blueprint for a better internet.

Что такое веб-компоненты?

Сегодня более 10% всех загружаемых страниц в Google Chrome — это страницы, содержащие веб-компоненты! Крупные технологические компании, такие как Apple, Google и Facebook, также изучают возможности использования веб-компонентов в своих приложениях и JavaScript фреймворках (например, Angular и React). Довольно впечатляющий результат для технологии, официально представленной в 2011 году и стандартизированной совсем недавно.

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

Что такое веб-компоненты?

Веб-компоненты — это полноценные элементы HTML с пользовательскими шаблонами, API и именами тегов. Они позволяют создавать новые HTML-теги, расширять существующие HTML-теги или расширять компоненты других разработчиков. Они могут быть использованы в любом веб-приложении, совместимы с (или без) любой библиотекой JavaScript или фреймворком (например, React, Angular, Vue.js, Next.js) и будут работать во всех современных браузерах.

Основой для него является API, который предоставляет основанный на веб-стандартах способ создания многократно используемых компонентов, используя только ванильный JavaScript, HTML и CSS.

Четыре самых используемых стандарта:

  1. Пользовательские элементы.
  2. Шаблоны HTML.
  3. Теневой DOM.
  4. Модули ES.

Давайте рассмотрим эти веб-стандарты более подробно.

1) Пользовательские элементы

Пользовательские элементы — это набор API, который позволяет создавать новые HTML-теги. С помощью этого API мы можем указать парсеру, как правильно создавать элемент и как он будет реагировать на изменения.

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

— Автономный пользовательский элемент, который можно использовать для создания совершенно новых элементов HTML.

— Настраиваемый встроенный элемент, который можно использовать для расширения существующих элементов HTML или других веб-компонентов.

Таким образом, API пользовательских элементов очень полезен для создания новых элементов HTML, но также и для расширения существующих или других веб-компонентов.

2) HTML-шаблоны

С помощью шаблонов HTML мы можем создавать многократно используемые фрагменты кода внутри обычного потока HTML, которые не отображаются сразу. Их можно клонировать и вставлять в документ во время выполнения JavaScript и скриптов, при этом ресурсы, находящиеся внутри, не будут извлекаться или выполняться до тех пор, пока шаблон не будет вставлен. Также не имеет значения, сколько раз используется шаблон — он клонируется в браузере и разбирается только один раз, а значит мы имеем большой прирост производительности!

Синтаксис HTML-шаблона выглядит следующим образом:

 

Когда страница рендерится, шаблон пуст. Содержимое хранится в DocumentFragment без контекста просмотра. Это сделано для того, чтобы не мешать остальной части приложения, то есть он отображается только по запросу, снова повышение производительности!

3) Теневой DOM

API Shadow DOM позволяет веб-браузерам изолировать фрагменты DOM (включая весь HTML и CSS) от основного дерева DOM документа. Его внутренняя работа почти аналогична работе , где содержимое изолировано от остальной части документа, с той лишь разницей, что мы по-прежнему имеем полный контроль над ним.

Что такое DOM?

С помощью HTML мы можем легко создавать страницы, которые имеют как представление, так и структуру. Нам, людям, это очень легко понять, но компьютерам требуется немного больше помощи, для этого введена объектная модель документа, или DOM.

Когда браузер загружает веб-страницу, он переводит HTML автора в модель данных, которая хранится в дереве узлов. Это дерево называется DOM и является живым представлением страницы. У него есть свойства, методы и, что самое интересное, им можно манипулировать с помощью. JavaScript!

Теневой DOM скрывает свое содержимое от окружающей среды (процесс называется инкапсуляцией), что предотвращает утечку кода CSS и JavaScript из пользовательского элемента и в него.

4) Модули ES

До появления ES-модулей в JavaScript не было системы модулей, как в других языках программирования. Разработчики прибегали к использованию тегов для загрузки файлов JavaScript в свои приложения. Позже начали появляться несколько определений модулей (например, CommonJS, AMD и UMD), но ни одно из них не стало стандартом. Все изменилось с появлением ES Modules, и у нас наконец-то появилась стандартная система модулей.

API ES Modules привносит в JavaScript стандартизированную систему модулей, которая обеспечивает способ объединения набора функций в библиотеку, которую можно повторно использовать в других файлах JavaScript.

Веб-компоненты и поддержка браузеров

Какие браузеры поддерживают веб-компоненты? В настоящее время все браузеры Evergreen (Chrome, Firefox и Edge) обеспечивают полную поддержку веб-компонентов. Это означает, что все API (т.е. пользовательские элементы, шаблоны HTML, теневой DOM и ES-модули) полностью поддерживаются!

Этот снимок экрана с сайта WebComponents.org показывает текущую поддержку веб-компонентов браузерами.

Internet Explorer

К сожалению, Internet Explorer 11 не поддерживает веб-компоненты, Microsoft прекратил поддержку IE11 17 августа 2021 года , до этого момента были доступны полифиллы , позволяющие максимально точно имитировать недостающие возможности браузера.

Safari

Safari поддерживает веб-компоненты, но он не поддерживает настраиваемые встроенные элементы, только автономные элементы. К счастью, полифиллы обеспечивают поддержку и для Safari.

Заключение

Современная веб-разработка становится сложнее с каждым днем, и сейчас, когда веб-платформа и ее стандарты созревают, имеет смысл использовать их более интенсивно. Веб-компоненты — это идеальный пример, основанный на 4 API, основанных на веб-стандартах (пользовательские элементы, шаблоны HTML, теневой DOM и ES-модули).

Постоянно растущая популярность Web-компонентов доказывает, что они останутся, и что сейчас самое время начать изучать эту удивительную технологию!

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

Мир веб-компонентов: разбираемся в трендах

Недавно я работал над исследованием технологии веб-компонентов для своей компании и обнаружил, что относительно сложно понять глобальное положение вещей на данный момент. Этой статьей я хочу попробовать решить эту проблему и предоставить вам отправную точку в путешествии в мир веб-компонентов.

Темы для рассмотрения

  • Поддержка браузерами.
  • Совместимость с фреймворками.
  • SSR + SEO/Боты.
  • Стилизация компонентов.
  • Специальные возможности (Accessibility).
  • Версионирование.
  • Загрузка в браузер.
  • Доступные инструменты.
  • Веб-компоненты vs Фреймворки.

Поддержка браузерами

IE и Edge (с движком Chakra) находятся вне игры, поскольку они не поддерживают Shadow DOM. Это делает использование веб-компонентов нецелесообразным из-за сложности полифилов.

Все остальные браузеры (Chrome, FF, Safari, учитывая две последние версии) прекрасно работают со всеми основными технологиями, которые нам нужны. Давайте взглянем на таблицу.

Технология Chrome FF Safari iOS Android
(CSS) ::slotted x x x (баги) x x
(CSS) :host x x x x x
(CSS) :host()
Есть обходной путь
x x x
(CSS) :host-context() x x
(CSS) :root x x x x x
(CSS) CSS Variables x x x x x
(JS) Constructible Stylesheets
Есть обходной путь
x
(JS) Custom Elements x x x x x
(JS) Shadow DOM x x x x x
(JS) Custom Event x x x x x

Совместимость с фреймворками

Все основные фреймворки, которые существуют в настоящее время, полностью поддерживают веб-компоненты. Но давайте посмотрим внимательно:

  • React/Preact — есть некоторые проблемы с расширенной интеграцией. И вам может понадобиться обернуть ваши веб-компоненты в React-компонент (может быть автоматизировано).
  • Vue.js — работает из коробки.
  • Angular — работает из коробки.

SSR (Рендеринг на стороне сервера) + SEO/Боты

Теоретически возможно полностью отрендерить веб-компонент на стороне сервера (и это даже работает для простых случаев), но. На сегодняшний день нет стабильной реализации этого процесса, а также способа представления Shadow DOM в HTML. К счастью, сообщество активно работает над решением.

Так что же нам тогда делать?

Ответ прост — вы можете жить без SSR для веб-компонентов. Конечно, этот подход имеет некоторые ограничения, но приходится работать с тем, что есть. Давайте посмотрим детальнее.

Чтобы рендерить веб-компоненты только на стороне клиента и не жертвовать SEO/совместимостью с ботами, вам нужно хранить контент в Light DOM и использовать атрибуты ARIA. Рассматривайте свои веб-компоненты как нативные элементы HTML. Вы можете согласиться с тем, что боту не нужно видеть Shadow DOM, например, для элемента , чтобы просмотреть его содержимое. Если компоненты хорошо спроектированы, ботам не нужно развернутое (Shadow + Light) DOM-дерево для получения текстового содержимого.

Давайте рассмотрим разметку компонента «Tab» в качестве примера:

 Title for tab 1 Content 1 Title for tab 2 Content 2 Title for tab 3 Content 3 

Как вы можете видеть из этого примера, боту не нужен доступ к Shadow DOM для понимания содержимого, представленного на странице.

Стилизация компонентов

Поскольку в наших компонентах мы используем Shadow DOM для внутренней разметки и слоты для контента, написание CSS поначалу может быть нетривиальной задачей. Давайте рассмотрим основные концепции, которые нужно держать в уме.

Изоляция CSS

Shadow DOM практически полностью изолирует свое содержимое от CSS, включенных на странице. В примере, приведенном выше, тег

(который находится внутри Shadow DOM) имеет текст, окрашенный в зеленый цвет, поскольку CSS свойство «color» было унаследовано.

Как включить CSS в Shadow DOM

В настоящее время самый простой способ включения CSS для веб-компонентов — это встраивание их inline в шаблон веб-компонента. Если вы включите их через тег , вы увидите FOUC во время загрузки страницы, точно так же, как в примере выше (обратите внимание на текст «I’m Shared CSS»).

Однако это ограничение можно преодолеть, скрыв весь контент Shadow DOM перед загрузкой связанного CSS или добавив внешний CSS-код компонента в код главной страницы (разумеется, в этом случае его следует каким-то образом заскоупить).

Поэтому остается ждать поддержки спецификации Constructable Stylesheets во всех основных браузерах. Это дало бы нам больше контроля над CSS.

Контекстно-зависимые стили

Часто наши компоненты имеют разные стили отображения в зависимости от переданных им аргументов. Классический пример — . Когда вы передаете аргумент «multiple» компоненту «select» — он полностью меняет свой внешний вид. Для достижения аналогичного поведения веб-платформа предлагает псевдокласс :host() (не путайте с :host ).

К сожалению, этот псевдокласс не поддерживается в Safari и iOS, поэтому мы не можем его использовать. В качестве обходного пути мы можем использовать возможности JS для ручного проецирования атрибутов и классов хост-элемента в корневой элемент Shadow DOM, чтобы получить возможность писать обычный CSS.

Стилизация контента внутри слота (< slot >)

Таблицы стилей, которые были добавлены в Shadow DOM, могут также применяться в элементах, находящихся внутри . Для этого у нас есть псевдоэлемент ::slotted() . Однако его поддержка браузерами все еще не идеальна. Посмотрите на приведенный выше пример: Safari не будет правильно обрабатывать селектор ::slotted(p)::before .

В качестве обходного пути мы можем добавить стили, отвечающие за стилизацию содержимого слота прямо на страницу (в Light DOM). Таким образом, следующий селектор ::slotted(p)::before для будет преобразован в my-component p::before . Это, естественно, несколько нарушает концепцию Shadow DOM, однако я не вижу другого пути на текущий момент.

Рекомендации

На этом этапе я бы рекомендовал продолжать (если вы уже это делаете) загружать CSS на страницу отдельным файлом с помощью тега и включать этот тег в каждое Shadow DOM-дерево. В настоящее время я использую следующий код для этого:

class MyComponent extends HTMLElement < constructor() < super(); this.attachShadow(< mode: 'open' >); this.__injectGlobalCSS(); >; __injectGlobalCSS() < const globalCssInclude = document.querySelector( 'head >[data-global-css="true"]' ); if (globalCssInclude === null) < console.warn(`Can't find global CSS for component $! Trying to render w/o it. `); return; > this.shadowRoot.appendChild(globalCssInclude.cloneNode(true)); > >;

Специальные возможности (Accessibility)

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

К счастью, есть решение, которое позволяет вернуть семантику в ваши веб-компоненты. Для этого вам просто нужно следовать спецификации WAI-AIRA. Так что, если вы уже позаботились о доступности, особых изменений в подходе здесь нет.

Давайте посмотрим на доступный компонент-слайдер, созданный с помощью технологии веб-компонентов:

Чтобы увидеть больше примеров полностью доступных веб-компонентов, вы также можете обратиться к следующим инструкциям от Google.

Версионирование

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

Давайте посмотрим на варианты, которые у нас есть.

Никогда не делайте breaking changes. Это принцип, который используют браузеры. И хотя это возможно сделать, и это может быть даже наилучшим вариантом для начала, очевидно, что данный подход противоречит принципу «fail fast, fail safe» и не способствует инновациям.

Управление версиями на основе тегов. Таким образом, вместо у вас будет для того, чтобы иметь несколько мажорных версий компонента на странице. Поэтому, если для «Фрагмента 1» требуется [email protected] , а для «Фрагмента 2» требуется [email protected] — будет использоваться только [email protected] . И если для «Фрагмента 1» требуется версия 1.1.5, а для «Фрагмента 2» требуется версия 2.0.0 — оба компонента будут зарегистрированы.

Версионирование по скоупу фрагмента. Таким образом, вместо у вас будет .

Загрузка в браузер для микросервисного фронтенда

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

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

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

Доступные инструменты

Библиотеки, которые вы можете использовать для создания своих веб-компонентов (отсортировано по моим предпочтениям сверху вниз):

  • LitElement — написан ребятами из Polymer, Google. На мой взгляд, самый оптимальный выбор.
  • Stencil — компилятор веб-компонентов плюс базовые классы. Создан командой Ionic. Его система сборки не очень совместима в Webpack.
  • SkateJS — крошечная обертка вокруг нативных API, которая позволяет использовать различные библиотеки рендера. Создано Trey Shugart, который подарил нам WC SSR PoC.
  • Svelte 3 — это скорее фреймворк, а не библиотека для упрощения создания веб-компонентов.
  • Riot.js.
  • Slim.js.
  • — последняя версия все еще в бете.
  • Smart HTML Elements — платный.

Но, постойте, действительно ли мне нужен какой-то инструмент для комфортного написания веб-компонентов? И простой ответ — нет, вы можете написать их, используя Vanilla JS. И это будет работать для большинства простых компонентов, которые вы будете писать.

Веб-компоненты vs Фреймворки

Если вкратце: они разные. Не пытайтесь заменить веб-компонентами старые добрые фреймворки, такие как Vue.js или React.

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

Другой вариант использования — если вы пишете open source библиотеку UI-компонентов (например, Bootstrap или MDC) и хотите сохранить ее независимой от фреймворка.

Пример Material Design Components в эру до веб-компонентов и с веб-компонентами.

Со временем фреймворки, скорее всего, начнут использовать Custom Elements и Shadow DOM внутри, но я не ожидаю увидеть широкого распространения данного подхода в ближайшие

Примечания

Если вы видите какие-либо пробелы или ошибки в статье, напишите в комментариях или отправьте мне на почту.

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

Полезные ссылки

  • Web Components: Mythbusters Edition
  • Using templates & slots
  • Complex guide & best practices from Google
  • Duplicate IDs cross Shadow DOM trees
  • The future of accessibility for custom elements

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

Web Components — будущее Web

Спустя какое время стало ясно, что основная идея Prototype вошла в противоречие с миром. Создатели браузеров ответили на возрождение Javascript добавлением новых API, многие из которых конфликтовали с реализацией Prototype.

Создатели браузеров поступают гармонично. Решение о новых API принимают с учётом текущих трендов в opensource сообществах. Так prototype.js способствовал появлению Array.prototype.forEach() , map() и т.д., jquery вдохновил разработчиков на HTMLElement.prototype.querySelector() и querySelectorAll() .

Код на стороне клиента становится сложнее и объёмнее. Появляются многочисленные фреймворки, которые помогают держать этот хаос под контролем. Backbone, ember, angular и другие создали, чтобы помочь писать чистый, модульный код. Фреймворки уровня приложения — это тренд. Его дух присутствует в JS среде уже какое-то время. Не удивительно, что создатели браузеров решили обратить на него внимание.

Web Components — это черновик набора стандартов. Его предложили и активно продвигают ребята из Google, но инициативу уже поддержали в Mozilla. И Microsoft. Шучу, Microsoft вообще не при делах. Мнения в комьюнити противоречивые (судя по комментариям, статьям и т.д.).

Основная идея в том, чтобы позволить программистам создавать “виджеты”. Фрагменты приложения, которые изолированы от документа, в который они встраиваются. Использовать виджет возможно как с помощью HTML, так и с помощью JS API.

Я пару недель игрался с новыми API и уверен, что в каком-то виде, рано или поздно эти возможности будут в браузерах. Хотя их реализация в Chrome Canary иногда ставила меня в тупик (меня, и сам Chrome Canary), Web Components кажется тем инструментом, которого мне не хватало.

Стандарт Web Components состоит из следующих частей:

Фрагменты HTML, которые программист собирается использовать в будущем.

Содержимое тегов парсится браузером, но не вызывает выполнение скриптов и загрузку дополнительных ресурсов (изображений, аудио…) пока мы не вставим его в документ.

Инструмент инкапсуляции HTML.

Shadow DOM позволяет изменять внутреннее представление HTML элементов, оставляя внешнее представление неизменным. Отличный пример — элементы и . В коде мы размещаем один тег, а браузер отображает несколько элементов (слайдеры, кнопки, окно проигрывателя). В Chrome эти и некоторые другие элементы используют
Shadow DOM.

Custom Elements позволяют создавать и определять API собственных HTML элементов. Когда-нибудь мечтали о том, чтобы в HTML был тег или ?

Templates

Концепция шаблонов проста. Хотя под этим словом в стандарте подразумевается не то, к чему мы привыкли.

В современных web-фреймворках шаблоны — это строки или фрагменты DOM, в которые мы подставляем данные перед тем как показать пользователю.

В web components шаблоны — это фрагменты DOM. Браузер парсит их содержимое, но не выполняет до тех пор, пока мы не вставим его в документ. То есть браузер не будет загружать картинки, аудио и видео, не будет выполнять скрипты.

К примеру, такой фрагмент разметки в документе не вызовет загрузку изображения.

  

Иван Иваныч

Хотя браузер распарсит содержимое . Добраться до него можно с помощью js:

 var tmpl = document.querySelector('#tmpl-user'); // содержимое var content = tmpl.content; var imported; // Подставляю данные в шаблон: content.querySelector('.name').innerText = 'Акакий'; // Чтобы скопировать содержимое и сделать его частью документа, // используйте document.importNode() // // Это заставит браузер `выполнить` содержимое шаблона, // в данном случае начнёт грузится картинка `photo.jpg` imported = document.importNode(content); // Результат импорта вставляю в документ: document.body.appendChild(imported); 

Пример работы шаблонов можно посмотреть здесь.

Все примеры в статье следует смотреть в Chrome Canary со включенными флагами:

  • Experimental Web Platform features
  • Enable HTML Imports
  • Enable Experimental Javascript
Для Чего?

На данный момент существует три способа работы с шаблонами:

    Добавить шаблон в скрытый элемент на странице. Когда он будет нужен,
    скопировать и подставить данные:

   

Минусы такого подхода в том, что браузер попытается “выполнить” код шаблона. То есть загрузить картинки, выполнить код скриптов и т.д.

  

Template Content

Минус в том, что приходится работать со строками. Это создаёт угрозу XSS, нужно уделять дополнительное внимание экранированию.

Shadow DOM

Инкапсуляция. Этого в работе с разметкой мне не хватало больше всего. Что такое Shadow DOM и как он работает проще понять на примере.

Когда мы используем html5 элемент код выглядит примерно так:

Но на странице это выглядит так:

audio element

Мы видим множество контролов, прогресбар, индикатор длины аудио. Откуда эти элементы и как до них добраться? Ответ — они находятся в Shadow Tree элемента. Мы можем даже увидеть их в DevTools, если захотим.

Чтобы Chrome в DevTools отображал содержимое Shadow DOM, в настройках DevTools, вкладка General, раздел Elements ставим галочку Show Shadow DOM.

Содержимое Shadow DOM тега в DevTools:

devtools shadow dom

Теория Shadow DOM

Shadow Tree — это поддерево, которое прикреплено к элементу в документе. Элемент в этом случае называется shadow host, на его месте браузер показывает содержимое shadow tree, игнорируя содержимое самого элемента.

Именно это происходит с тегом в примере выше, на его месте браузер рендерит содержимое shadow tree.

Фишка shadow dom в том, что стили, определённые в нём с помощью , не распространяются на родительский документ. Также у нас есть возможность ограничить влияние стилей родительского документа на содержимое shadow tree. Об этом позже.

Посадить теневое дерево

Shadow DOM API позволяет пользователям самостоятельно создавать и
манипулировать содержимым shadow tree.

пример

  
Этот текст пользователь не увидит.

custom shadow dom

Проекции, тег

Проекция — это использование содержимого хоста в shadow tree. Для этого в стандарте есть тег .

Важно, что проецирует содержимое хоста, а не переносит его из хоста в shadow tree. Потомки хоста остаются на своём месте, на них распространяются стили документа (а не shadow tree). это своего рода окно между мирами.

пример

   

Варлам

Бодрый Пёс

content demo

Стили в Shadow DOM

Инкапсуляция стилей — основная фишка shadow DOM. Стили, которые определёны в shadow tree имеют силу только внутри этого дерева.

Досадная особенность — использовать в shadow tree внешние css файлы нельзя. Надеюсь, это поправят в будущем.

пример

    

Зелёный фон в примере получит только « внутри shadow tree. То
есть стили «не вытекут» в основной документ.

green

Наследуемые стили

По-умолчанию наследуемые стили, такие как color , font-size и другие, влияют на содержимое shadow tree. Мы избежим этого, если установим shadowRoot.resetStyleInheritance = true .

пример

   

Host Content

inherit styles

Авторские стили

Чтобы стили документа влияли на то, как выглядит shadow tree, используйте свойство applyAuthorStyles .

пример

   /* В стилях документа */ .border  

Изменяя значение applyAuthorStyles , получаем разный результат:

no to author styles

yes to author styles

Селекторы ^ и ^^

Инкапсуляция это здорово, но если мы всё таки хотим добраться до shadow tree и изменить его представление из стилей документа, нам понадобится молоток. И кувалда.

Селектор div ^ p аналогичен div p с тем исключением, что он пересекает одну теневую границу (Shadow Boundary).

Селектор div ^^ p аналогичен предыдущему, но пересекает ЛЮБОЕ количество теневых границ.

пример

   /* В стилях документа */ .shadow-host ^ p.shadow-p  

cat in the hat

Зачем нужен Shadow DOM?

Shadow DOM позволяет изменять внутреннее представление HTML элементов, оставляя внешнее представление неизменным.

Возможное применение — альтернатива iframe . Последний чересчур изолирован. Чтобы взаимодействовать с внешним документом, приходится изобретать безумные способы передачи сообщений. Изменение внешнего представления с помощью css просто невозможно.

В отличие от iframe , Shadow DOM — это часть вашего документа. И хотя shadow tree в некоторой степени изолировано, при желании мы можем изменить его представление с помощью стилей, или расковырять скриптом.

Custom Elements

Custom Elements — это инструмент создания своих HTML элементов. API этой части Web Components выглядит зрело и напоминает директивы
Angular. В сочетании с Shadow DOM и шаблонами, кастомные элементы дают возможность создавать полноценные виджеты вроде , или .

Чтобы избежать конфликтов, согласно стандарту, кастомные элементы должны содержать дефис в своём названии. По-умолчанию они наследуют HTMLElement . Таким образом, когда браузер натыкается на разметку вида , он парсит его как HTMLElement . В случае , результат будет HTMLUnknownElement .

пример

  
dog type
x-dog type

x-dog

API кастомного элемента

Мы можем определять свойства и методы у нашего элемента. Такие, как метод play() у элемента .

В жизненный цикл (lifecycle) элемента входит 4 события, на каждое мы можем повесить callback:

  • created — создан инстанс элемента
  • attached — элемент вставлен в DOM
  • detached — элемент удалён из DOM
  • attributeChanged — атрибут элемента добавлен, удалён или изменён

    Создаём прототип элемента.

Прототип должен наследовать HTMLElement или его наследника,
например HTMLButtonElement :

 var myElementProto = Object.create(HTMLElement.prototype, < // API элемента и его lifecycle callbacks >); 
 var myElement = document.registerElement('my-element', < prototype: myElementProto >); 

пример

  
Cat's life:

cats life

Зачем нужны Custom Elements?

    хорошо подходят для низкоуровневой вёрстки, тогда как Custom Elements позволят писать модульный, удобочитаемый код на высоком уровне.

Shadow DOM и Custom Elements дают возможность создавать независимые от контекста виджеты, с удобным API и инкапсулированным внутренним представлением.

HTML Imports

Импорты — простое API, которому давно место в браузерах. Они дают возможность вставлять в документ фрагменты разметки из других файлов.

пример

   var link = document.querySelector('link[rel="import"]'); // Доступ к импортированному документу происходит с помощью свойства // *import*. var importedContent = link.import; importedContent.querySelector('article'); 

Object.observe()

Ещё одно приятное дополнение и часть Web Components (кажется), это API для отслеживания изменений объекта Object.observe() .

Этот метод доступен в Chrome, если включить флаг Experimental Web Platform features.

пример

 var o = <>; Object.observe(o, function (changes) < changes.forEach(function (change) < // change.object содержит изменённую версию объекта console.log('property:', change.name, 'type:', change.type); >); >); o.x = 1 // property: x type: add o.x = 2 // property: x type: update delete o.x // property: x type: delete 

При изменении объекта o вызывается callback, в него передаётся массив
свойств, которые изменились.

TODO widget

Согласно древней традиции, вооружившись этими знаниями, я решил сделать простой TODO-виджет. В нём используются части Web Components, о которых я рассказывал в статье.

Добавление виджета на страницу сводится к одному импорту и одному тегу в теле документа.

пример

    

todo widget

Заключение

С развитием html5 браузеры стали нативно поддерживать новые медиа-форматы. Также появились элементы вроде . Теперь у нас огромное количество возможностей для создания интерактивных приложений на клиенте. Этот стандарт также представил элементы , , и другие. Разметка стала “иметь смысл”, приобрела семантику.

На мой взгляд, Web Components — это следующий шаг. Разработчики смогут создавать интерактивные виджеты. Их легко поддерживать, переиспользовать, интегрировать.

Код страницы не будет выглядеть как набор “блоков”, “параграфов” и “списков”. Мы сможем использовать элементы вроде “меню”, “новостная лента”, “чат”.

Конечно, стандарт сыроват. К примеру, импорты работают не так хорошо, как шаблоны. Их использование рушило Chrome время от времени. Но объём нововведений поражает. Даже часть этих возможностей способна облегчить жизнь web-разработчикам. А некоторые заметно ускорят работу существующих фреймворков.

Некоторые части Web Components можно использовать уже сейчас с помощью полифилов. Polymer Project — это полноценный фреймворк уровня приложения, который использует Web Components.

Ссылки

  • Web Components Intro, W3C Working Draft
  • Shadow DOM, W3C Editor’s Draft
  • Примеры к этой статье
  • Bug 811542 — Implement Web Components, Bugzilla@Mozilla

Eric Bidelman, серия статей и видео о Web Components:

  • HTML’s New Template Tag: standardizing client-side
    templating
  • Shadow DOM 101
  • Shadow DOM 201: CSS and Styling
  • Shadow DOM 301: Advanced Concepts & DOM APIs
  • Custom Elements: defining new elements in HTML
  • HTML Imports: #include for the web
  • components (видео)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *