Инкапсуляция великолепна и обеспечивает лучшую структуру и удобочитаемость.

Этот факт также относится к DOM, и с добавлением Shadow DOM и его интерфейса ShadowRoot теперь есть эффективные способы извлечения внутренней логики веб-компонента из исходного DOM.

Библиотеки компонентов пользовательского интерфейса могут использовать веб-компоненты и Shadow DOM, чтобы еще больше контролировать настройку своих компонентов.

Теневые Части

Помимо атрибутов и пользовательских свойств, также существует возможность определить теневые части, на которые можно нацелить псевдоэлемент ::part()CSS, чтобы обеспечить конкретную настройку для потребителя.

Ограничения настройки

Хотя в большинстве случаев определенные части компонента обеспечивают достаточную полезность для настройки, существуют ограничения.

В качестве примера я хотел бы взять Компонент Ionic Datetime, так как я также буду использовать этот компонент позже в статье для более практической демонстрации.

Этот компонент не только красиво выглядит, но и автоматически обрабатывает дополнительную логику, такую ​​как ограничение дат, установка правильной локализации и часового пояса самостоятельно (документация Ionic великолепна).

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

Если элемент в Shadow DOM не определен как часть, нет надлежащего способа получить доступ и, следовательно, стилизовать этот элемент извне компонента.

Или, по крайней мере, до Constructable Stylesheets их не было.

Что такое конструируемые таблицы стилей

Интерфейс CSSStyleSheet предоставляет альтернативу document.createElement('style') для создания и применения <style> элементов.

Это особенно полезно при работе с Shadow DOM. На web.dev есть отличная статья о таблицах стилей Constructable от Джейсона Миллера, в которой подробно объясняется этот интерфейс.

Я настоятельно рекомендую вам прочитать его статью для дальнейшего объяснения, поскольку я продолжу свой пример компонента datetime в следующем разделе.

Использование таблиц стилей Constructable Style для стилизации теневых элементов

Во-первых, давайте взглянем на элементы, которые мы хотим стилизовать в Shadow DOM компонента Ionic Datetime:

Ясно видно, что ни заголовок календаря, ни тело, ни временная метка не доступны в качестве теневых частей. Чтобы стилизовать их независимо, мы можем использовать Constructable Stylesheets:

Шаг 1. Определите правила CSS

Определенные правила должны быть объявлены в виде строки, так как это единственный тип, который в настоящее время поддерживает API.

Вот пример того, как это может выглядеть:

Шаг 2: Создайте новую таблицу стилей

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

Я обычно извлекаю эту логику во вспомогательную функцию, чтобы мой код оставался чистым (и да, я использую TypeScript):

Шаг 3: Получите ShadowRoot компонента

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

Поскольку я в основном использую Vue, я помещаю этот код в обратный вызов жизненного цикла onMounted. Однако это не обязательно, вы можете выполнить следующие шаги в любой функции.

Только не забудьте проверить, был ли успешно получен ShadowRoot:

Шаг 4: Добавьте таблицу стилей в ShadowRoot

Этот заголовок не на 100% правильный. На самом деле нам нужно заменить текущие таблицы стилей, присутствующие в ShadowRoot, потому что adoptedStyleSheets — это замороженный массив:

Подробнее о adoptedStyleSheets можно прочитать здесь, а также в статье Джейсона.

Полностью настраиваемый компонент

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

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

К сожалению, на сегодняшний день не все браузеры полностью поддерживают веб-API CSSStyleSheet. На изображении ниже видно, что конструктор для создания нового CSSStyleSheet недоступен для Safari.

Конструктор необходим для выполнения этой работы.

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

К счастью, существует полифилл с открытым исходным кодом. Автор утверждает, что этот полифилл поддерживает веб-API CSSStyleSheet во всех основных браузерах.

Заключение

На мой взгляд, добавление этого веб-API — это здорово. Я бы посоветовал использовать его с осторожностью.

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

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