如何在JS中获取所有子节点,包括所有的“孙子节点”?

82

我希望能够扫描一个div以获取其中所有子节点,包括嵌套在其他元素内的节点。目前我的代码如下:

var t = document.getElementById('DivId').childNodes;
for(i=0; i<t.length; i++) alert(t[i].id);

但它仅获取Div的子级而不是孙级。谢谢!修改:这个问题太模糊了,抱歉。以下是一个范例:http://jsfiddle.net/F6L2B/ body.onload脚本无法在JSFiddle上运行,但它可以工作,除了'Me Second'和'Me Third'输入字段没有被分配tabIndex,因此被跳过。
4个回答

122

这是最快和最简单的方法,而且它适用于所有浏览器:

myDiv.getElementsByTagName("*")

6
请注意,与childNodes不同,此方法不会获取“注释”或“文本”后代节点(尽管这可能是您想要的)。 - aplaice
令人惊讶的是,它被 IE6+ 支持。 - S.Serpooshan
2
它获取的是 Element,而不是 Node - tsh
要获取所有子文本节点(或注释),使用document.evaluate以父节点为上下文节点,表达式为“.//text()”是非常高效的。 - Joakim

34

如果你想寻找现代浏览器上的所有HTMLElement,你可以使用以下代码:

myDiv.querySelectorAll("*")

19
使用myDiv.getElementsByTagName("*")几乎肯定会更快,并且也可以在较旧的浏览器上使用。 - rvighne
@rvighne,你的评论应该被标记为这个问题的答案。 - thednp
这实际上是非常巧妙的。对于这个答案表示赞扬! - Jose A
1
这里的 myDiv 是什么? - xkeshav
或者直接使用 document.querySelectorAll('#DivId *'),如果不想/不需要单独存储 myDiv - brc-dd

16

那么曾孙辈呢?

要任意深入,您可以使用递归函数。

var alldescendants = [];

var t = document.getElementById('DivId').childNodes;
    for(let i = 0; i < t.length; i++)
        if (t[i].nodeType == 1)
            recurseAndAdd(t[i], alldescendants);

function recurseAndAdd(el, descendants) {
  descendants.push(el.id);
  var children = el.childNodes;
  for(let i=0; i < children.length; i++) {
     if (children[i].nodeType == 1) {
         recurseAndAdd(children[i]);
     }
  }
}

如果你只想要孙子,那么你可以去掉递归(可能需要重命名函数)。
function recurseAndAdd(el, descendants) {
  descendants.push(el.id);
  var children = el.childNodes;
  for(i=0; i < children.length; i++) {
     if (children[i].nodeType == 1) {
         descendants.push(children[i].id);
     }
  }
}

只需要对你的函数做一个小改动,以确保只有元素节点(标签)被添加到结果中。在将其添加到集合之前,您需要检查 if (el.nodeType == 1) { ... } - Strelok
@Strelok - 现在看起来怎么样 - 在你写那个评论的时候,我可能已经用另一种方式修复了它。 - Adam Rackis
2
不,它仍然是一样的。childNodes返回所有东西,包括节点内部的文本,例如span、属性、注释等。如果您需要子元素节点(span、div、label、input等),则需要检查if (el.nodeType == 1) { ... },其中1表示ELEMENT节点类型。 - Strelok
我试图澄清上面的问题。也许你能更好地看到我想做什么。谢谢你的帮助! - Michael Swarts
使用querySelectorAll怎么样?var t = document.getElementById('DivId').querySelectorAll('*'); - CC.
显示剩余4条评论

4

如果其他人想获取该树中的所有节点,而不仅仅是元素,这里是一个2022年的JavaScript代码片段:

function getDescendantNodes(node, all = []) {
  all.push(...node.childNodes);
  for (const child of node.childNodes) 
    getDescendantNodes(child, all);
  return all;
}

提示:之后,您可以使用全局变量Node筛选出您所需的nodeTypenodes = getDescendantNodes($0); nodes.filter(n => n.nodeType === Node.TEXT_NODE)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接