如何document.getElementsByTagName(“*”)包含打开的shadowRoot元素?

How do I document.getElementsByTagName("*") including open shadowRoot elements?

提问人:Jeff 提问时间:10/24/2022 最后编辑:Jeff 更新时间:10/24/2022 访问量:216

问:

正如标题所说,如何获取所有元素,包括打开的元素及其子元素,其中也可能包含打开的 shadowRoot 元素?shadowRoot

我在 SO 上发现了一些类似的问题,但它们都返回 (inner|outer)HTML,这是相似但非常不同的逻辑。我想返回一个包含shadowRoot元素的对象或数组。

我不介意从切换到,如果它让事情变得更容易,但我认为它不会。getElementsByTagName("*")querySelectorAll("*")

编辑

我认为不可能在这里完成我想要的东西,例如返回页面上所有元素的对象/数组,包括嵌套元素。同样,我的最终目标是在页面上的每个元素上,包括 shadowRoot 节点。shadowRootgetComputedStyle()

我唯一能想到的就是在 SO 上使用类似于 this 或 this on SO 的函数来获取所有 HTML,将其添加到页面中隐藏的某个地方,解析它,然后选择性地将其从页面中删除。

任何建议或想法都是值得赞赏的。

JavaScript的

评论

1赞 Sebastian Simon 10/24/2022
由于影子根旨在封装自定义元素的内容,因此我很难理解为什么您需要它。从理论上讲,使用如下代码进行开放阴影根是可能的: .const allElems = (root) => Array.from(root.querySelectorAll("*")).flatMap((elem) => (elem.shadowRoot ? [ elem, ...allElems(elem.shadowRoot) ] : [ elem ])); allElems(document);
0赞 Jeff 10/24/2022
我需要在shadowRoot中的节点上。getComputedStyle()

答:

-1赞 Ronnie Royston 10/24/2022 #1

只需使用递归来遍历整个?document

function walkTree(node) {
  if (node === null) {
    return;
  }
  // do something with node
  for (let i = 0; i < node.childNodes.length; i++) {
    walkTree(node.childNodes[i]);
  }
}

用例是这样的:

function walkTree(node) {
  if (node === null) {
    return;
  }
  // do something with node
  for (let i = 0; i < node.childNodes.length; i++) {
    if(node.childNodes[i].tagName){
      console.log(node.childNodes[i].tagName);
    }
    walkTree(node.childNodes[i]);
  }
}
document.getElementById("rt").attachShadow({mode: 'closed'});
var doc = document.getElementsByTagName("HTML")[0]
walkTree(doc);
<html>
    <head>
        <title>This is <span>the title</span></title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    </head>
    <body class="my-class">
        <main>
          <h1>This is a header</h1>
          <div>
            <div class="something">
              <p>This is a <span>paragraph</span></p>
            </div>
            <div id="shadow-rt">
                <div>
                    <span id="shadow-dom-child"></span>
                </div>
            </div>
          </div>
        </main>
    </body>
</html>

评论

0赞 Jeff 10/24/2022
我认为这是正确答案的开始,但我对 js 还不够好,无法了解如何递归包含节点并构建数组/对象。.shadowRoot