Ich möchte wissen, was der Unterschied zwischen querySelector
und getElementsByClass
ist. Code> Was ist der Unterschied?
Über diesen Link habe ich erfahren, dass ich mit querySelector
document.querySelector(".myclass")
schreiben kann, um die Datei mit dem Klassennamen< ;code>myclass und document.querySelector("#myid")
, um das Element mit der ID myid
abzurufen. Aber ich kann diese Funktionalität bereits mit getElementsByClassName
und getElementById
erreichen. Welches sollte bevorzugt werden?
Außerdem arbeite ich in XPages und die IDs werden dynamisch generiert, enthalten Doppelpunkte und sehen so aus: view:_id1:inputText1
. Wenn ich also document.querySelector("#view:_id1:inputText1")
schreibe, funktioniert es nicht. Aber wenn ich document.getElementById("view:_id1:inputText1")
schreibe, funktioniert es. Irgendwelche Ideen, warum das passiert?
对于这个答案,我将
querySelector
和querySelectorAll
称为querySelector*,将getElementById
、getElementsByClassName
、getElementsByTagName
和getElementsByName
称为getElement*。这些信息的很多可以在规范中进行验证,很多是我在编写时运行的各种基准测试得出的。规范:https://dom.spec.whatwg.org/
主要区别
querySelector
和getElementById
都返回单个元素。querySelectorAll
和getElementsByName
都返回NodeList。getElementsByClassName
和getElementsByTagName
都返回HTMLCollection。NodeList和HTMLCollection都被称为元素的集合。这些概念在下表中总结。
详细信息、提示和示例
HTMLCollection不像NodeList那样类似于数组,不支持.forEach()。我发现扩展运算符对绕过这个问题很有用:
[...document.getElementsByClassName("someClass")].forEach()
每个元素和全局
document
都可以访问所有这些函数,除了getElementById
和getElementsByName
,它们只在document
上实现。链式使用getElement*调用而不是使用querySelector*将提高性能,特别是在非常大的DOM上。即使在小的DOM和/或非常长的链上,通常也更快。然而,除非您知道需要性能,否则应该优先选择querySelector*的可读性。
querySelectorAll
通常更难重写,因为您必须在每一步中从NodeList或HTMLCollection中选择元素。例如,以下代码不起作用:document.getElementsByClassName("someClass").getElementsByTagName("div")
因为您只能在单个元素上使用getElements*,而不是集合,但如果您只想要一个元素,那么:
document.querySelector("#someId .someClass div")
可以写成:
document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]
注意在返回集合的每一步中使用
[0]
,以获取集合的第一个元素,最终结果只有一个元素,就像使用querySelector
一样。由于所有元素都可以使用querySelector*和getElement*调用,因此可以同时使用这两个调用进行链式操作,这在您想要一些性能提升但无法避免使用无法用getElement*调用编写的querySelector时非常有用。
尽管通常很容易判断一个选择器是否可以只使用getElement*调用来编写,但有一种情况可能不明显:
document.querySelectorAll(".class1.class2")
可以重写为
document.getElementsByClassName("class1 class2")
在使用querySelector*获取的静态元素上使用getElement*将导致元素相对于querySelector复制的静态DOM子集是动态的,但相对于完整文档DOM是静态的...这就是简单的动态/静态元素解释开始分崩离析的地方。您应该尽量避免需要担心这个问题的情况,但如果确实存在这种情况,请记住querySelector*调用在返回引用之前会复制它们找到的元素,而getElement*调用则会直接获取引用而不复制。
querySelector*和
getElementById
以前序、深度优先的方式遍历元素,在规范中称为“树顺序”。对于其他getElement*调用,从规范中我无法确定它们是否与树顺序相同,但getElementsByClassName(".someClass")[0]
可能在每个浏览器中结果不可靠。getElementById("#someId")
应该是可靠的,即使您的页面上有多个相同的id副本。当我在处理无限滚动页面时,我不得不研究这个问题,我认为这可能是一个常见的情况,性能成为一个问题。我们的代码中有onScroll事件,其中包含querySelectorAll调用。即使调用被限制速率,如果您滚动到足够远的位置,页面也会崩溃,此时将有太多调用迭代太多元素,浏览器无法跟上。DOM的大小在这种用例中是相关的,因此在无限滚动页面上运行的代码中,更倾向于使用getElement*调用。
语法和浏览器支持。
querySelector
在你想要使用更复杂的选择器时更有用。例如,所有从属于foo类的元素的列表项:
.foo li
:
字符在选择器中有特殊含义。你需要对它进行转义。(选择器转义字符在JS字符串中也有特殊含义,所以你也需要转义它)。