NodeList何时生效,何时是静态的?

时间:2015-01-27 04:02:03

标签: javascript html nodelist

从MDN获取NodeList

  

在某些情况下,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的所有各个部分?这里有规则吗?

2 个答案:

答案 0 :(得分:94)

有关每种方法的详细信息,如果它是否有效,但似乎没有确定它的标准惯例。

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中,也可能不在DOM中。

  

NodeList对象是节点的集合......   NodeList接口提供有序的抽象   节点的集合,没有定义或约束这个   集合已实施。 DOM中的NodeList对象是实时的。

http://www.w3.org/TR/DOM-Level-3-Core/core.html#td-live

听起来不错,对吧?

  

集合是表示DOM节点列表的对象。一个   集合可以是实时的也可以是静态的。除非另有说明,否则a   收藏必须是现场。

http://www.w3.org/TR/2012/WD-dom-20120405/#collections

因此静态集合将在规范中指明。因此,通过这种逻辑,document.querySelectorAll()是一个集合,但它在DOM中。因为虽然集合可能是也可能不是,但在 DOM中的集合必须是实时的...这种区别并不是非常有用。

嗯,这是确定collection是否有效的快速方法;它将集合成员的克隆附加到DOM(因此它将匹配选择器),并检查长度是否已更改,然后将其删除(因此页面不受影响)

<强>样本

&#13;
&#13;
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;
}



divs1 = document.getElementsByClassName('c');
console.log("document.getElementsByClassName('c'):",divs1.toString()); //"[object HTMLCollection]"


divs2 = document.querySelectorAll('.c');
console.log("document.querySelectorAll('.c'):     ",divs2.toString()); //"[object NodeList]"

divs3 = document.getElementsByName('mydiv');
console.log("document.getElementsByName('mydiv'): ",divs3.toString()); //"[object NodeList"]

console.log("isLive(divs1)",isLive(divs1)); //true
console.log("isLive(divs2)",isLive(divs2)); //false
console.log("isLive(divs3)",isLive(divs3)); //true
&#13;
<html>

<body>
  <div class="c" name="mydiv">C1</div>
  <div class="c" name="mydiv">C2</div>
</body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:3)

我不知道是否有中心参考,但blog post说:

  

document.getElementsByTagName()document.getElementsByTagNameNSdocument.getElementsByClassName()是唯一可用于返回“实时”节点列表的选项。看看这些方法,你可能会气馁,但不要这样做。