什么时候NodeList是活的,什么时候是静态的?
从NodeList的 MDN:
在某些情况下,NodeList是一个实时集合,这意味着DOM中的变化反映在集合中。 例如,Node.childNodes是活动的:
var parent = document.getElementById('parent'); var child_nodes = parent.childNodes; console.log(child_nodes.length); // let's assume "2" parent.appendChild(document.createElement('div')); console.log(child_nodes.length); // should output "3"
在其他情况下,NodeList是一个静态集合,意味着DOM中的任何后续更改都不会影响集合的内容。 document.querySelectorAll返回一个静态的NodeList。
所以….有点讨厌! 有什么中央参考哪些方法返回实时列表,哪些返回静态列表,而不必单独检查DOM API的各个部分? 这里有什么规定吗?
关于每个方法的详细信息,如果它是否存在,但似乎没有一个标准的惯例来确定它。
document.getElementsByClassName()
是一个HTMLCollection
,并且是活的。
document.getElementsByTagName()
是一个HTMLCollection
,并且是活的。
document.getElementsByName()
是一个NodeList
并且是活的。
document.querySelectorAll()
是一个NodeList
并且不是活的。
HTMLCollection
似乎永远是活的
HTMLCollection是一个节点列表。 单个节点可以通过序号索引或节点的名称或ID属性进行访问。
注意:假设HTML DOM中的集合是活的,意味着当底层文档发生更改时,它们会自动更新。
http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-75708506
所以,HTML集合总是 “在DOM中”,而nodeList
是一个更通用的构造,可能或不可能在DOM中。
一个NodeList对象是一个节点的集合… NodeList接口提供了一个有序的节点集合的抽象,没有定义或约束如何实现这个集合。 DOM中的NodeList对象是活的。
http://www.w3.org/TR/DOM-Level-3-Core/core.html#td-live
听起来不错,对吧?
集合是表示DOM节点列表的对象。 集合可以是实时的也可以是静态的。 除非另有说明,收集必须是现场的。
http://www.w3.org/TR/2012/WD-dom-20120405/#collections
所以静态集合将在规范中被指示。 所以,通过这个逻辑, document.querySelectorAll()
是一个集合,但它不在 DOM中。 因为虽然集合可能或不可能是活的,但DOM中的集合必须是活的…这种区别不是很有帮助。
那么,这是一个快速的方法来确定一个collection
是否存在; 它将集合的一个成员的克隆附加到DOM
(所以它将匹配select器),并检查长度是否改变,然后将其删除(所以页面不受影响)
function isLive(collection) { if (collection.length < 1) { return undefined; //inconclusivw } let body = document.getElementsByTagName('body')[0]; let l1 = collection.length; let clone = collection.item(0).cloneNode(); clone.style.display = "none"; body.appendChild(clone); let l2 = collection.length; body.removeChild(clone); return l2 !== l1; }
DEMO
HTML
<html><body> <div class="c" name="mydiv">C1</div> <div class="c" name="mydiv">C2</div> </body></html>
JS
divs1=document.getElementsByClassName('c'); console.log(divs1.toString());//"[object HTMLCollection]" divs2=document.querySelectorAll('.c'); console.log(divs2.toString());//"[object NodeList]" divs3=document.getElementsByName('mydiv'); console.log(divs3.toString());//"[object NodeList"] console.log(isLive(divs1));//true console.log(isLive(divs2));//false console.log(isLive(divs3));//true
我不知道是否有一个中心的参考,但这个博客文章说:
document.getElementsByTagName()
,document.getElementsByTagNameNS
和document.getElementsByClassName()
是返回“活动”节点列表的唯一可用选项。 看这些方法,你可能会气馁,但不要这样做。