HTML getElementsByClassName返回长度为0的HTMLCollection

21

我试图使用 jsdocument.getElementsByClassName 来定位一个 HTML 元素,实际上是一张表格的标题。

以下是代码:

console.log(document.getElementsByClassName('gtableheader'));

通过 Firebug,我可以看到它记录了一个 HTMLCollection,当我点击它时,它显示:

-> 0         tr.gtableheader
   length    1

所以它确实定位到了我想要的元素。

但是当我使用以下代码时:

console.log(document.getElementsByClassName('gtableheader').length);

那么输出结果是0。这很奇怪,对此有什么想法吗?


1
你能让我们看看你的HTML代码吗?你是动态创建元素吗? - showdev
1
你是在文档元素之后调用它吗?比如在加载事件之后? - RobG
可能是重复的问题:document.getElementsByClassName('name') has a length of 0 - showdev
6个回答

22
因为 getElementsByClassName 返回的是一个 活动的 集合,因此对象的 length 属性为 0,因为此时DOM中没有该类名的元素。由于控制台显示了对象的实时表示形式,因此当元素添加到DOM中时,它会显示所有匹配的元素。
DOM解析器从上到下解析文档,当它到达标签时,解析并将其DOM表示形式(HTMLElement接口的实例)添加到文档对象模型中。您应该将脚本标签移动到 body 标签的末尾,或者侦听 DOMContentLoaded 事件,该事件在初始HTML文档完全加载和解析后触发。

2
<h1>这是因为 getElementsByClassName 返回一个 LIVE 集合</h1> 这是一个非常重要的事实需要知道。 - RBT
@RBT,你介意解释一下为什么吗? - undefined

6
使用getElementsByClassName(),可以返回文档中所有具有该类名的元素作为一个NodeList。这个对象代表了一个可以通过索引号访问的节点集合,起始索引号为0。为了访问NodeList中的元素,您需要使用循环。
当您运行console.log(document.getElementsByClassName('gtableheader').length);时,您会看到0,因为当您运行它时,没有具有类名gtableheader的元素。您能够在控制台中看到项目,是因为document.getElementsByClassName()返回一个实时更新的集合,该集合在添加新元素时更新。
此外,在您使用的代码中长度为0时,您可以使用下面的代码来访问类名。
document.getElementsByClassName('gtableheader')[0].style.color="red";

如果你想访问类中的所有元素,可以使用for循环。
var x = document.getElementsByClassName('gtableheader');
for (var i = 0; i < x.length; i++) {
    x[i].style.color = "red";
}

更多信息请参考:http://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp

21
这似乎没有回答问题。你还提到了getElementsByClassName返回的nodeList的length属性,然而你只是从你分配结果的变量x中读取了它。当我在这个页面上运行document.getElementsByClassName('question').length时,由于该类只有一个元素,结果为1。因此,你没有回答为什么OP的问题返回0的答案。 - Val
4
实际上,真正的问题是我在元素加载之前尝试访问它,这就是为什么长度为“0”的原因。 - chrisTina
另一个问题是element没有style属性。虽然它可以工作,但IDE一直在抱怨它应该是HTMLElement。如何解决这个问题? - Kokodoko
只需要把代码放在document ready里面就可以了,谢谢。但是逻辑上有点奇怪,先获取元素组,然后读取变量的长度,但仍然返回0。这是JavaScript... :) 变量名为xyz,获取方式为document.getElementsByClassName('xyz'),控制台输出xyz和xyz.length。 - Võ Minh
document.getElementsByClassName创建一个新的HTMLCollection还是仅返回现有的HTMLCollection? - SuperSim135

6
使用这个来使它运作。
window.addEventListener("load", function(event) {
    console.log(document.getElementsByClassName('gtableheader').length);
});

5

我曾遇到过类似的问题,但这里的其他答案没有导致我的解决方案。最终我意识到,在我的代码运行时,DOM还没有完全构建好,因此数组为空。我在控制台看到的已填充数组是在DOM完全形成并且脚本完成后存在的。

对我有效的方法是将需要数组的代码包装在MutationObserver中,并将其设置为监视包含将动态生成的部分的硬编码div(请参见此StackOverflow答案MDN文档)。

试试这个:

var divArray = document.getElementById('hardCodedContainer');

var observer = new MutationObserver(function(){
   console.log(document.getElementsByClassName('gtableheader').length);
   console.log(document.getElementsByClassName('gtableheader'));
};

observer.observe(divArray, { attributes: false, childList: true, subtree: true });

// When you've got what you need, you should call this function to trigger a disconnect 
function classesFound(){
   observer.disconnect();
};

0

只需将您的 <script> 标签放在 </body> 标签之前即可。

如果未在 <body> 标签末尾添加 <script> 标签,则可能导致DOM在此时尚未就绪,从而阻止JavaScript对其进行操作,从而导致未知行为


0

我遇到了一个问题,就是在动态创建元素后立即请求元素,但通过使用setTiemout()方法解决了这个问题。


3
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

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