如何使用JavaScript获取用户代理阴影根中的元素?

Yar*_*dov 10 html javascript web-component shadow-dom

我需要从Shadow DOM获取元素并进行更改.我怎么能这样做?

<div>
     <input type="range" min="100 $" max="3000 $">
</div>
Run Code Online (Sandbox Code Playgroud)

Dom*_*omi 19

要回答OP问题的一般版本:

从页面上的任何位置查询影子元素?

感觉还是缺少shadow root API。它似乎毫无用处querySelectorAll,因为它querySelectorAll实际上不会再获得所有匹配元素,因为它忽略了shadowRoots. 也许有一个 API 可以解决这个问题,但由于我没有找到任何 API,所以我编写了自己的 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();
}
Run Code Online (Sandbox Code Playgroud)
// 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
Run Code Online (Sandbox Code Playgroud)


Sup*_*arp 18

您无法访问由浏览器创建的Shadow DOM来显示控件,该控件#shadow-root (user-agent)在开发工具中称为a .<input>就是一个例子.

您只能使用该选项访问打开的自定义Shadow DOM(您自己创建的那些){ mode: 'open' }.

element.attachShadow( { mode: 'open' } )
Run Code Online (Sandbox Code Playgroud)

更新

它是最UX标准的HTML元素真:<input>,<video>,<textarea>,<select>,<audio>,等.

  • 什么来源?用户代理 Shadow DOM 是浏览器供应商的本机实现,因此它们没有记录并且永远无法访问。根据规范,仅开放 Shadow DOM。 (2认同)

Ism*_*OUH 11

这是一个例子:

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);
Run Code Online (Sandbox Code Playgroud)

演示:

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);
Run Code Online (Sandbox Code Playgroud)
<div id="example">Element</div>
Run Code Online (Sandbox Code Playgroud)

我希望这能帮到您.

  • 被否决,因为这描述了使用 Javascript API 创建影子根,但它没有描述访问浏览器实现的影子根。指示您无法访问浏览器生成的影子根(例如Chrome中的#shadow-root)的响应更为正确。不过,也感谢您解释如何创建一个。 (4认同)
  • 这不回答如何访问用户代理元素的影子根(已由浏览器创建)。它展示了如何访问自定义元素的影子根(由开发人员创建)。 (4认同)
  • 这在最近的 Firefox 中似乎不起作用: `"message": "TypeError: container.createShadowRoot is not a function"` (2认同)