Современные веб-сайты часто содержат данные и виджеты из разных источников, размещенные на одной странице. Например, один сайт может легко содержать видеоплеер YouTube, кнопку «Нравится» в Facebook, кнопку «Твитнуть» в Twitter и многое другое. Тот факт, что код от многих поставщиков может сосуществовать на одной странице, является не чем иным, как маленьким чудом. И хотя текущие реализации работают, они далеки от идеальных. Например, добавление кнопки «Мне нравится» на страницу требует использования неуклюжего тега <iframe>. В настоящее время нет элегантного способа обеспечить инкапсуляцию для этих виджетов.
Инкапсуляция — это особенность объектно-ориентированных языков программирования, которая позволяет объектам управлять своими собственными данными и ограничивать доступ к ним. Согласно этой парадигме, объект предоставляет интерфейс с внешним миром, который может использоваться для взаимодействия с его данными. Поддерживая этот интерфейс, объект может помешать стороннему коду произвольно уничтожать свои личные данные. К сожалению для веб-разработчиков, HTML пока не предлагает такой интерфейс. Столкновения CSS и JavaScript являются источником постоянной заботы разработчиков библиотек и виджетов. Инкапсуляция позволит разработчикам писать свой код и знать, что он будет работать должным образом, даже при наличии других скриптов и таблиц стилей. W3C решает эту проблему с помощью спецификации теневого DOM , которая в настоящее время находится в стадии разработки.
Shadow DOM поддеревья
Дерево DOM состоит из множества функциональных поддеревьев — одного или нескольких узлов DOM, которые реализуют определенную функциональность. Например, функциональность кнопки «Мне нравится» реализуется одним набором узлов, а кнопка «Твитнуть» — другим набором. Цель теневого DOM — обеспечить функциональную инкапсуляцию для этих поддеревьев. Это достигается путем отделения функциональных поддеревьев от дерева документов (и друг от друга). Это разделение теневых поддеревьев DOM известно как теневая граница . Правила CSS и запросы DOM не пересекают теневую границу и, таким образом, обеспечивают инкапсуляцию.
Любой элемент в дереве документа может содержать одно или несколько теневых поддеревьев DOM. Узлы, в которых размещаются поддеревья теневых DOM, называются теневыми узлами . Однако, поскольку теневые поддеревы DOM не взаимодействуют с обычным деревом документов, возможно, что узел является теневым хостом и все еще имеет дочерние узлы в дереве документа.
Рисунок 1, взятый из спецификации W3C, иллюстрирует концепцию теневых поддеревьев DOM. Зеленые узлы слева представляют типичное дерево документа. Один из узлов DOM помечен как теневой хост. Пунктирная стрелка, выходящая из этого узла, пересекает теневую границу и ссылается на несколько поддеревьев DOM-тени. Корнем каждого теневого поддерева DOM является теневой корень (представленный квадратным узлом на рисунке). Теневой корень — это особый тип DOM-фрагмента документа, который инкапсулирует его дочерние элементы из внешнего мира. Однако потомки теневого корня — это просто стандартные узлы DOM.
Рендеринг Shadow DOM
Когда страница отображается, дерево документа и теневые поддеревы DOM отображаются как единое дерево. Дерево документа отображается так, как обычно. Однако при обнаружении теневого хоста браузер игнорирует свое поддерево документа и вместо этого отображает теневое поддерево DOM узла. Рисунок 2 иллюстрирует эту концепцию. Обратите внимание, что хотя теневой хост отображается, теневой корневой узел — нет.
Включение Shadow DOM
Хотя теневой DOM является горячей темой, в настоящее время он поддерживается только в качестве экспериментальной функции в Chrome. Чтобы включить теневой DOM в Chrome, сначала перейдите по URL-адресу «chrome: // flags». Затем найдите параметр «Включить Shadow DOM» и нажмите «Включить». Опция показана ниже на рисунке 3. Наконец, Chrome перезагрузится. На этом этапе вы можете начать писать страницы, использующие теневой DOM.
Пример Shadow DOM
В этом разделе рассматривается пример теневой страницы DOM. Источник HTML страницы показан ниже. Тело страницы содержит элемент <div>, который будет использоваться в качестве теневого хоста. Внутри <div> находится дочерний узел <span>, в котором четко указано, что он не является частью теневого DOM. Когда страница завершает загрузку, обработчик событий присоединяет теневое поддерево DOM к теневому хосту. Поддерево теневого DOM создается путем создания нового объекта WebKitShadowRoot (префикс WebKit, вероятно, будет отброшен после полной поддержки теневого DOM). Теневой хост передается как единственный параметр конструктору ShadowRoot. Затем элемент <span> с именем «shadowChild» добавляется в поддерево теневого DOM. Текстовое содержимое «shadowChild» указывает, что оно является частью теневого DOM.
<! DOCTYPE html> <html lang = "en"> <Голова> <title> Пример Shadow DOM </ title> <meta charset = "UTF-8" /> <Стиль> span { красный цвет; } #shadowHost { граница: 1px сплошной черный } </ Стиль> <Скрипт> window.addEventListener ("load", function () { var shadowHost = document.getElementById ("shadowHost"); var shadowRoot = new WebKitShadowRoot (shadowHost); var shadowChild = document.createElement ("span"); shadowChild.textContent = "Это часть теневого DOM"; shadowRoot.appendChild (shadowChild); }, ложный); </ Скрипт> </ HEAD> <Тело> <div id = "shadowHost"> <span id = "child"> Это не часть теневого DOM </ span> </ DIV> </ Body> </ Html>
Страница примера, отображаемая Chrome 20, показана на рисунке 4. На этой странице стоит отметить несколько вещей. Во-первых, теневой DOM <span> отображается вместо дерева документов <span>. Хотя дерево документа <span> не отображается, оно все же доступно через скрипт. Второе, на что следует обратить внимание, это то, что тень <span> не окрашена в красный цвет в соответствии с правилом CSS для элементов <span>. Это указывает на то, что теневой DOM фактически инкапсулирован в дереве документа.
На рисунке 5 показано дерево документов, отображаемое инспектором элементов Chrome. Дерево документа не отражает какую-либо часть теневого DOM. Браузеры, которые не поддерживают теневой DOM, будут отображать это дерево.
ShadowRoot DOM Методы
Поскольку теневые DOM-узлы инкапсулированы в дереве документа, обычные методы, связанные с DOM, такие как getElementById (), не могут использоваться для доступа к ним. Однако объекты ShadowRoot предоставляют множество одинаковых функций для доступа к их поддереву DOM. Например, объекты ShadowRoot поддерживают следующие распространенные методы запроса DOM.
- getElementById ()
- getElementsByClassName ()
- getElementsByTagName ()
- getElementsByTagNameNS ()
- querySelector ()
- querySelectorAll ()
Для удобства объект ShadowRoot также поддерживает свойство innerHTML. Как и в случае с обычным DOM, теневой DOM «innerHTML» можно читать и записывать. Пример использования показан ниже.
shadowRoot.innerHTML = "<span> innerHTML созданный контент </ span>";
CSS через границу тени
По умолчанию правила CSS, определенные вне теневого корня, не применяются к теневым узлам DOM. Однако объект ShadowRoot может разрешить правилам CSS пересекать границу тени через логическое свойство applyAuthorStyles. Установка этого свойства в true переопределяет поведение по умолчанию. Пример использования показан ниже. На предыдущей странице примера это приведет к тому, что теневой DOM <span> будет окрашен в красный цвет.
shadowRoot.applyAuthorStyles = true;
То, что нужно запомнить
- Теневой DOM обеспечивает функциональную инкапсуляцию для веб-разработчиков.
- Теневые хосты — это элементы, которые поддерживают поддеревья теневых DOM.
- Корневой узел теневого поддерева DOM называется теневым корнем.
- Теневые поддеревы DOM заменяют поддеревья дерева документов во время визуализации
- Объект ShadowRoot предоставляет много общих функций, связанных с DOM.