Firefox 3.5 中的 DOM 遍历

Firefox 3.5 包含对两个 W3C DOM 遍历规范的新支持。第一个是 元素遍历 API,专注于使逐元素遍历更容易,第二个是 NodeIterator 接口,它使查找所有节点类型变得更加容易。

元素遍历 API

元素遍历 API 的目的是使开发人员更容易遍历 DOM 元素,而不必担心中间文本节点、注释节点等。这长期以来一直是网页开发人员的难题,特别是对于像 document.documentElement.firstChild 这样的情况,它会根据文档的空格结构产生不同的结果。

元素遍历 API 引入了一些 新的 DOM 节点属性,可以使此遍历变得更加简单。

以下是现有 DOM 节点属性及其新对应项的完整分解。

目的 所有 DOM 节点 仅 DOM 元素
第一个 .firstChild .firstElementChild
最后一个 .lastChild .lastElementChild
上一个 .previousSibling .previousElementSibling
下一个 .nextSibling .nextElementSibling
长度 .childNodes.length .childElementCount

这些属性为 DOM 规范提供了一个相当简单的补充(老实说,它们本来就应该在规范中)。

但是,有一个属性明显缺失:.childElements(作为 .childNodes 的对应项)。此属性(包含 DOM 元素子元素的实时 NodeSet)在规范的先前版本中,但似乎在一段时间内被裁剪掉了。

但并非全无希望。目前,Internet Explorer、Opera 和 Safari 都支持 .children 属性,它提供了原本应该由 .childElements 实现的功能的超集。当对元素遍历 API 的支持最终登陆 Firefox 3.5 时,对 .children 的支持也包含在内。这意味着每个主要浏览器现在都支持此属性(远远早于所有浏览器支持其他真正元素遍历规范)。

元素遍历 API(和 .children)的一些实际应用示例

单击时显示下一个元素

someElement.addEventListener("click", function(){
    this.nextSiblingElement.style.display = "block";
}, false);

为所有子元素添加类

for ( var i = 0; i < someElement.children.length; i++ ) {
    someElement.children[ i ].className = "active";
}

NodeIterator API

NodeIterator 是一个相对古老的 API,尚未得到广泛采用,并且刚刚在 Firefox 3.5 中实现。具体来说,NodeIterator API 的设计目的是允许轻松遍历 DOM 文档中的所有节点(这包括文本节点、注释等)。

API 本身相当复杂(包含许多对大多数开发人员来说并不立即重要的功能),但如果您想将其用于一些更简单的任务,它会非常容易。

API 通过创建 NodeIterator(使用 document.createNodeIterator)并传入一系列过滤器来工作。NodeIterator 能够返回文档中的所有节点(或给定节点的上下文中),因此您需要将其过滤以仅显示您想要的节点。下面是一个简单的示例。

构造一个 NodeIterator 来迭代文档中的所有注释节点。

var nodeIterator = document.createNodeIterator(
    document,
    NodeFilter.SHOW_COMMENT,
    null,
    false
);

var node;

while ( (node = nodeIterator.nextNode()) ) {
    node.parentNode.removeChild( node );
}

一旦构造完毕,NodeIterator 就是双向的(您可以使用任何方向移动,使用 previousNodenextNode)。

也许 API 最好的用法是在遍历常用的(但难以遍历的)节点(如注释和文本节点)上。由于已经存在一些用于遍历 DOM 元素的 API(例如 getElementsByTagName),因此这确实为节点遍历的常规方法提供了受欢迎的喘息机会。

关于 John Resig

更多由 John Resig 撰写的文章…


12 个评论

  1. steve

    我认为 IE 中的 document.all 集合不是实时集合?例如,当我使用 id/name 属性向 DOM 添加新元素(在页面加载之后)时,它们不一定添加到集合中。

    或者,关于 IE 在完全支持此功能之前的处理方式,我是否遗漏了什么?

    2009 年 6 月 19 日 下午 07:36

  2. Horia Dragomir

    我记得这些关于节点与元素的问题曾经是过去那些伟大的框架统治互联网之前的一大难题。哦,我记得很清楚…

    除了此增强带来的便利性之外,我想速度和可靠性也会提高,对吧?

    让我们看看其他浏览器实现此功能的速度如何。

    2009 年 6 月 19 日 下午 07:38

  3. steve

    哎呀!别管我… 我不知怎么地把这句话读错了… 从句子中的其他地方提取了“all”这个词… 哦,互联网橡皮擦… 当我需要你的时候你在哪里!

    2009 年 6 月 19 日 下午 07:38

  4. Gilberto Ramos

    看起来非常有用!

    2009 年 6 月 19 日 下午 07:43

  5. […] 刚刚发布了关于 Firefox 3.5 中一些新的 DOM 遍历 API 的概述。这篇文章的前半部分主要是我之前元素遍历 API 的回顾 […]

    2009 年 6 月 19 日 下午 08:53

  6. Elijah Grey

    文档类型是否只应具有 .nextSibling 属性,而不应具有 .nextElementSibling 属性?

    document.firstChild.nextSibling === document.documentElement 并且 document.firstChild.nextElementSibling === undefined 对我来说。

    2009 年 6 月 19 日 下午 09:05

  7. Илья Казначеев

    “这长期以来一直是网页开发人员的难题”直到出现了 Prototype,现在已经不复存在了。
    当 DOM 已经解决的时候,为什么要费心让它膨胀?

    2009 年 6 月 19 日 下午 09:16

  8. […] Resig 发表了关于现在在 Firefox 3.5 中使用的 DOM 遍历方法的文章,然后又发表了一篇关于 NodeIterator API 优点的文章。他并不印象深刻:这个 API 是 […]

    2009 年 6 月 19 日 下午 12:05

  9. Erik

    在您调用函数的 API 函数列表中,您调用了函数 ‘nextElementSibling’,但在示例中它是 ‘nextSiblingElement’。哪个是正确的?

    2009 年 6 月 20 日 上午 03:07

  10. […] 原文地址:DOM Traversal in Firefox 3.5 系列地址:颠覆网络35天 […]

    2009 年 6 月 22 日 上午 00:41

  11. MJiA

    第一个代码片段中的“this.nextSiblingElement.style.display = “block”;” 是否应该为“this.nextElementSibling.style.display = “block”;
    ?”

    2009 年 6 月 22 日 上午 01:13

  12. […] 来自 Mozilla Hacks 博客的系列翻译文章中,今天我将介绍 John Resig 撰写的文章 DOM Traversal in Firefox 3.5 的翻译(他以创建库 […]

    2009 年 7 月 29 日 上午 04:32

本文的评论已关闭。