Можно ли получить доступ к элементам 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?

3 ответа

Решение

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

К сожалению, вы не можете создать общедоступный интерфейс JavaScript для своей Shadow DOM без использования другой передовой спецификации под названием Custom Elements. Если вы решите это сделать, это так же просто, как добавить пользовательские публичные методы в прототип вашего элемента. Из них вы можете получить доступ к внутренностям вашего 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 (см. 2-й пример здесь).

Переменные CSS

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

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

<body>
    <div id="container"></div>
    <script>
        //Shadow Root
        var root = container.createShadowRoot()
        //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>

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

document.getElementById('itemId').root 

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

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

Другие вопросы по тегам