Могу ли я выбрать элементы Polymer, которые существуют в Shadow DOM?

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

Я использую FluentAutomation, который знает только работу с селекторами CSS и некоторыми jQuery.

Есть ли способ идентифицировать элементы внутри Shadow DOM с помощью CSS-селекторов?

2 ответа

Решение

Вы хотите выбрать узел dom, который является частью теневого домена?

поскольку там нет селектора, который пронизывает теневой домен, вам придется указать полный путь к узлу dom. Пример источника:

<my-app>
  #shadow-root
    <h3 part="header">My App Header</h3>
    <my-dialog>
      #shadow-root
        <p part="header">My Dialog Header</p>
        <my-alert>
          #shadow-root
            <span part="header">My Alert Header</span>
        </my-alert>
        <my-alert>
          #shadow-root
            <span part="header">My Alert Header</span>
        </my-alert>
    </my-dialog>
</my-app>

Чтобы выбрать первое мое оповещение, вам нужно сделать

document.querySelector('my-app').shadowRoot.querySelector('my-dialog').shadowRoot.querySelector('my-alert');

если у вас есть идентификаторы, как так

<my-app id="app">
  #shadow-root
    <h3 part="header">My App Header</h3>
    <my-dialog id="dialog">
      #shadow-root
        <p part="header">My Dialog Header</p>
        <my-alert id="alert1">
          #shadow-root
            <span part="header">My Alert Header</span>
        </my-alert>
        <my-alert id="alert2">
          #shadow-root
            <span part="header">My Alert Header</span>
        </my-alert>
    </my-dialog>
</my-app>

Вы можете использовать более оптимизированный путь.

document.querySelector('my-app').$.dialog.$.alert1

PS: если вам интересно, в работах есть селектор, который позволяет вам пробить теневой дом для определенных "экспортированных" частей...
Spec: https://tabatkins.github.io/specs/css-shadow-parts/
Сообщение в блоге: https://meowni.ca/posts/part-theme-explainer/

В итоге я использовал скрипт, предоставленный коллегой, который ищет элементы в теневых куполах:

    (() => {
            if (window.DeepShadowDom !== undefined) {
                return;
            }

            const findAll = (selector, root = document) => {
                let elements = [ ];

                Array.prototype.push.apply(elements, root.querySelectorAll(selector));

                Array.prototype.slice.call(root.querySelectorAll('*'))
                    .filter(e => e.shadowRoot !== null)
                    .forEach((currentElement, index, array) => {

                        let candidates = findAll(selector, currentElement.shadowRoot);

                        Array.prototype.push.apply(elements, candidates);
                    });

                return elements;
            };

            const find = (selector, root = document) => {
                let elements = findAll(selector, document);

                if (elements.length > 1) {
                    throw new Error(`Multiple results returned by selector '${selector}'`);
                }

                return elements[0];
            };

            window.DeepShadowDom = { find, findAll };
        })();

Затем можно найти элемент, выбрав DeepshadowDom.Find(селектор)

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