Блог веб разработки статьи | видеообзоры | исходный код

Блог веб разработки статьи | видеообзоры | исходный код

webfanat вконтакте webfanat youtube

Shadow dom javascript

Shadow dom javascript

Доброго времени суток! В данной небольшой статье я вам расcкажу про Shadow dom(теневой dom) в javascript. Итак, поехали!

Как вы знаете работа с html элементами в javascript осуществляются через работу с DOM. DOM представляет собой архитектуру элементов(тегов) построенную в браузере из html кода. Для просмотра данной архитектуры достаточно зайти в любой инспектор элементов. К примеру в google chrome для того чтобы вызвать инспектор необходимо нажать горячие клавиши ctrl + shift + i и в результате вы увидите dom дерево веб страницы. Данный DOM является открытым и может наследовать все стили, скрипты подключенные к данной странице.

В современных браузерах помимо открытого dom дерева поддерживается еще так называемый теневой dom(скрытое dom дерево). Shadom dom представляет собой изолированную архитектуру элементов от основного dom(открытого dom дерева). Некоторые сложные элементы веб страницы такие как к примеру video, audio, input[range] и т. п. состоят из отдельных компонентов построенных с помощью shadow dom.

Рассмотрим на примере тега video.

<video controls src="video.webm"></video>

Если мы зайдем в инспектор кода и посмотрим на данный тег то увидим точно такую же структуру описанную нами в html коде. Никаких дополнительных компонентов мы не увидим, потому что изначально теневое дерево скрыто. Чтобы его просмотреть переходим в инспектор(на примере браузера google chrome), в правом верхнем меню отладочной панели рядом с крестиком кликаем по значку с тремя точками и выбираем пункт настройки(settings). Далее в колонке Elements активируем чекбокс 'Show user agent shadow DOM'. После возвращаемся в инспектор и смотрим на тег video. Как видите он теперь не пустой. Если мы его раскроем то увидим там такую строчку '#shadow-root (user-agent)' которая содержит множество различных элементов. Поздравляю! Вы попали в скрытое dom дерево веб страницы, а точнее тега video. Теперь вы знаете что видеоплеер html5 состоит из множества разных компонентов(тегов). Следует учесть что dom тега видео формируется браузером и мы не можем иметь доступ к его скрытым элементам для манипулирования. Однако ничто не мешает нам создавать у элементов свои скрытые компоненты, чем мы далее и займемся.

Итак введение закончилось, переходим к коду.

<style>
  p{
    color:red;
  }
</style>
<p>Заголовок текста</p>
<div class="shadow"></div>
<p>Окончание текста</p>
<script>
  document.querySelectorAll('p').forEach((elem) => {
    elem.style.fontSize = '10px';
  });
</script>

Здесь создана простая верстка к которой применены стили и скрипты. Элемент div с классом shadow будет root элементом нашего скрытого dom дерева(shadow). Причем желательно чтобы root элемент не содержал в себе ничего, так как при создании в нем shadow dom все его содержимое перестанет отображаться. Это следует запомнить!

var div = document.querySelector('.shadow');
var shadow =  div.attachShadow({mode: 'open'});

Этим кодом мы создаем внутри элемента '.shadow' теневой dom(shadow dom). Если зайдем в инспектор кода и раскроем данный элемент то увидим #shadow-root (open).mode

{mode: 'open'} - означает что мы может обращаться к теневому dom дереву через элемент с помощью свойства shadowRoot пример:

console.log(div.shadowRoot);

Здесь будет в консоль возвращена ссылка на dom дерево элемента '.shadow' по сути это то что возвращено в переменную 'shadow'.

Если поставить {mode: 'closed'} то свойство 'shadowRoot' будет возвращать значение null.

Теневое dom дерево мы создали, теперь можно его наполнять данными(html кодом, стилями, скриптами).

var div = document.querySelector('.shadow');
var p = document.createElement('p');
p.innerText = 'Середина текста';
var shadow =  div.attachShadow({mode: 'open'});
shadow.appendChild(p);

В данном примере мы создали тег 'p' с текстом 'Середина текста' и добавили в скрытое dom дерево. Обратите внимание что работа с shadow dom ничем не отличается от работы с обычным dom деревом. Однако как вы уже могли заметить внешние стили и скрипты к тегу 'p' в shadow dom не применились. Это говорит о том что контекст теневого дерева полностью изолирован от обычного DOM.

Расширим пример:

var div = document.querySelector('.shadow');
var p = document.createElement('p');
p.innerText = 'Середина текста';
var shadow =  div.attachShadow({mode: 'open'});


shadow.innerHTML = `
<style>
p{
  color:green;
  cursor:pointer;
  }
</style>
`;
var script = document.createElement('script');
script.innerHTML = `
  shadow.querySelector('p').addEventListener('click', function(){
  this.style.fontSize = '20px';
});
`;
shadow.appendChild(p);
shadow.appendChild(script);

Здесь в shadow dom были добавлены стили и скрипт к тегу 'p'. Обратите внимание что в самом скрипте мы обращаемся к тегу 'p' не через document(document.querySelector('p')), а переменную shadow(shadow.querySelector('p')) которая является ссылкой на корневой элемент shadow dom.

var shadow =  div.attachShadow({mode: 'open'});

Так сделано потому что элементы shadow dom не содержаться в обычном dom и обращаться к ним по селектору мы может только через корневой элемент.

Если кратко подвести итог, то получается что shadow dom позволяет нам создавать полностью независимые от основного контекста и друг от друга компоненты которые могут включать в себя собственную структуру(html элементы), стили(css) и логику(javascript).

Для взаимодействия компонентов теневого dom между собой или основным контекстом мы можем использовать ссылку на корневой элемент. Пример:

var div = document.querySelector('.shadow');
var shadow =  div.attachShadow({mode: 'open'});

Переменная shadow является корневым элементом shadow dom у селектора '.shadow'. К примеру если мы хотим поменять цвет у элемента 'p' в теневом дереве.

var div = document.querySelector('.shadow');
var p = document.createElement('p');
p.innerText = 'Середина текста';
var shadow =  div.attachShadow({mode: 'open'});
shadow.appendChild(p);

shadow.querySelector('p').style.color = 'orange';

Установили цвет у элемента 'p' - orange(оранжевый) через обращение к корневому элементу(root).

Общую суть я надеюсь вы поняли. На этом у меня все. Не забывайте подписываться на группу Вконтакте и переходите на канал Youtube.

Всем спасибо за внимание! Пока.

Оцените статью:

Статьи

Разработки

Комментарии

В данном разделе пока нет комментариев!

Реклама

Запись экрана

Данное расширение позволяет записывать экран и выводит видео в формате webm