Как получить элемент в теневом корне user-agent с помощью JavaScript?

Мне нужно получить элементы из Shadow DOM и изменить его. Как я могу это сделать?

<div>
     <input type="range" min="100 $" max="3000 $">
</div>

3 ответа

Решение

Вот пример:

var container = document.querySelector('#example');
//Create shadow root !
var root = container.createShadowRoot();
root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>';

//Access the element inside the shadow !
//"container.shadowRoot" represents the youngest shadow root that is hosted on the element !
console.log(container.shadowRoot.querySelector(".test").innerHTML);

Демо - версия:

var container = document.querySelector('#example');
//Create shadow root !
var root = container.createShadowRoot();
root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>';

//Access the element inside the shadow !
console.log(container.shadowRoot.querySelector(".test").innerHTML);
<div id="example">Element</div>

Я надеюсь, что это поможет вам.

Вы не можете получить доступ к Shadow DOM, созданному браузером для отображения элемента управления, который называется #shadow-root (user-agent) в Dev Tools. <input> это один пример.

Вы можете получить доступ только к открытым пользовательским Shadow DOM (тем, которые вы создали сами), с помощью { mode: 'open' } вариант.

element.attachShadow( { mode: 'open' } )

Обновить

Это верно для большинства стандартных HTML-элементов UX: <input>, <video>, <textarea>, <select>, <audio>, так далее.

Чтобы ответить (обобщенная версия) на вопрос ОП:

Как вы можете запрашивать элементы, независимо от того, находится ли он в shadowRoot или нет?

Такое чувство, что теневого корневого API все еще не хватает (или я просто недостаточно хорошо его знаю). Но это в основном делает несколько бесполезным, в том, что querySelectorAllна самом деле больше не будет получать все совпадающие элементы, поскольку он просто игнорирует всех предков в . Возможно, есть API, который это исправляет, но на всякий случай:

Вот простая функция, которая рекурсивно перебирает все shadowRootsи получает все совпадающие элементы на странице, а не только элементы одного shadowRoot.

      /**
 * Finds all elements in the entire page matching `selector`, even if they are in shadowRoots.
 * Just like `querySelectorAll`, but automatically expand on all child `shadowRoot` elements.
 * @see https://stackoverflow.com/a/71692555/2228771
 */
function querySelectorAllShadows(selector, el = document.body) {
  // recurse on childShadows
  const childShadows = Array.from(el.querySelectorAll('*')).
    map(el => el.shadowRoot).filter(Boolean);

  // console.log('[querySelectorAllShadows]', selector, el, `(${childShadows.length} shadowRoots)`);

  const childResults = childShadows.map(child => querySelectorAllShadows(selector, child));
  
  // fuse all results into singular, flat array
  const result = Array.from(el.querySelectorAll(selector));
  return result.concat(childResults).flat();
}
      // examples:
querySelectorAllShadows('td'); // all `td`s in body
querySelectorAllShadows('.btn') // all `.btn`s in body
querySelectorAllShadows('a', document.querySelector('#right-nav')); // all `a`s in right menu
Другие вопросы по тегам