Подтвердить что ты не робот

Возможно ли получить доступ к элементам Shadow DOM через родительский документ?

Этот вопрос больше нацелен на создаваемые пользователем теневые элементы DOM, но для доступности я буду использовать тип ввода date для этого вопроса:

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

<input type="date">
    #document-fragment
        <div pseudo="-webkit-datetime-edit">
            <div pseudo="-webkit-datetime-edit-fields-wrapper">
                <span role="spinbutton">dd</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">mm</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">yyyy</span>
            </div>
        </div>
        <div></div>
        <div pseudo="-webkit-calendar-picker-indicator"></div>

Методы и свойства, связанные с входом date, вообще не ссылаются на теневую DOM (JSFiddle), поэтому Мне было интересно, как (если вообще) можно получить эти теневые элементы DOM?

4b9b3361

Ответ 1

Как @int32_t правильно указал, что Shadow DOM, по определению, является способом заполнения узла DOM, который вы хотите скрыть от внешних источников (Encapsulation). Дело в том, что вы, как автор компонента, можете точно выбрать, какие части будут видны вне CSS или JavaScript, а какие нет.

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

Тем не менее, вы можете выставить хуки для CSS для доступа к внутренностям вашего Shadow DOM без использования пользовательских элементов. Есть два способа сделать это:

  1. Псевдо-элементы
  2. Переменные CSS

Псевдо-элементы

Chrome и Firefox предоставляют определенные части Shadow DOM CSS с помощью специальных псевдоэлементов. Вот ваш пример ввода date с добавлением правила CSS, которое применяется только к числовой части поля даты посредством использования предоставленного Chrome -webkit-datetime-edit псевдоэлемента.

Вот частичный список доступных псевдоэлементов WebKit. Вы также можете просто включить опцию Show Shadow DOM в DevTools и искать атрибуты с именем pseudo.

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

Переменные CSS

Еще лучше использовать CSS-переменные, которые можно включить с помощью Enable experimental WebKit features в about:flags в Chrome. Затем посмотрите эту скрипку, которая использует CSS-переменные, чтобы сообщить Shadow DOM, какой цвет он должен использовать для своей "темы".

Ответ 2

Теперь (2016) вы можете получить доступ к открытым созданным пользователем теневым DOM-элементам (но не созданным пользовательским агентом shadow DOM!) С помощью метода querySelector в корневом каталоге Shadow DOM:

<body>
    <div id="container"></div>
    <script>
        //Shadow Root
        ̶v̶a̶r̶ ̶r̶o̶o̶t̶ ̶=̶ ̶c̶o̶n̶t̶a̶i̶n̶e̶r̶.̶c̶r̶e̶a̶t̶e̶S̶h̶a̶d̶o̶w̶R̶o̶o̶t̶(̶)̶
        //new syntax:
        var root = container.attachShadow( { mode: "open" } )

        //Inside element
        var span = document.createElement( "span" )
        span.textContent = "i'm inside the Shadow DOM"
        span.id = "inside"
        root.appendChild( span )

        //Access inside element
        console.log( container.shadowRoot.querySelector( "#inside" ) )
    </script>
</body>

//Shadow Root
var root = container.createShadowRoot()

//Inside element
var span = document.createElement( "span" )
span.textContent = "i'm inside the Shadow DOM"
span.id = "inside"
root.appendChild( span )

//Access inside element
function get() 
{
  alert( container.shadowRoot.querySelector( "#inside" ).id )
}
<!DOCTYPE html>
<html>
<head>
    <title></title>
	<meta charset="utf-8" />
</head>
<body>
	<div id="container"></div>
    <button onclick="get()">Get</button>
	<script>
	</script>
</body>
</html>

Ответ 3

Вы не можете получить доступ к содержимому Shadow DOM из сценариев вне DOM Dadow. Инкапсуляция - это цель Shadow DOM.

Ответ 4

Да. Вам просто нужно вызвать.root или.shadowRoot. Вот пример,

document.getElementById('itemId').root 

Вы не получите элемент shadow dom без innerText или innerHTML в родительском элементе dom.