第10章 文档对象模型DOM 10.1 Node节点类型

DOM是针对 HTML 和 XML 文档的一个 API(应用程序编程接口) 。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。DOM 脱胎于Netscape 及微软公司创始的 DHTML (动态 HTML) , 但现在它已经成为表现和操作页面标记的真正的跨平台、语言中立的方式。

节点

DOM 可以将任何 HTML 或 XML 文档描绘成一个由多层节点构成的结构。

每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。

以HTML 为例:

<html>

<head>

<title>Sample Page</title>

</head>

<body>

<p>Hello World!</p>

</body>

</html>

例子中,文档节点只有一个子节点,即 <html> 元素,我们称之为文档元素。

文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在 HTML 页面中,文档元素始终都是 <html> 元素。在 XML 中,没有预定义的元素,因此任何元素都可能成为文档元素。

Node 类型

DOM1 级定义了一个 Node 接口,该接口将由 DOM 中的所有节点类型实现。在JavaScript 中是作为 Node 类型实现的;除了 IE 之外,在其他所有浏览器中都可以访问到这个类型。JavaScript 中的所有节点类型都继承自 Node 类型,因此所有节点类型都共享着相同的基本属性和方法。

每个节点都有一个 nodeType 属性,用于表明节点的类型。节点类型由在 Node 类型中定义的下列12 个数值常量来表示,任何节点类型必居其一:

Node.ELEMENT_NODE (1);

Node.ATTRIBUTE_NODE (2);

Node.TEXT_NODE (3);

Node.CDATA_SECTION_NODE (4);

Node.ENTITY_REFERENCE_NODE (5);

Node.ENTITY_NODE (6);

Node.PROCESSING_INSTRUCTION_NODE (7);

Node.COMMENT_NODE (8);

Node.DOCUMENT_NODE (9);

Node.DOCUMENT_TYPE_NODE (10);

Node.DOCUMENT_FRAGMENT_NODE (11);

Node.NOTATION_NODE (12)。

通过比较上面这些常量,可以很容易地确定节点的类型,例如:

if (someNode.nodeType == Node.ELEMENT_NODE){ //在 IE 中无效

alert("Node is an element.");

}

为了确保跨浏览器兼容,最好还是将 nodeType 属性与数字值进行比较,如下所示:

if (someNode.nodeType == 1){ // 适用于所有浏览器

alert("Node is an element.");

}

要了解节点的具体信息,可以使用 nodeName 和 nodeValue 这两个属性。如:

if (someNode.nodeType == 1){

value = someNode.nodeName; //nodeName 的值是元素的标签名

}

节点之间关系。

每个节点都有一个 childNodes 属性,其中保存着一个NodeList 对象。 NodeList 是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。

虽然可以通过方括号语法来访问 NodeList 的值,而且这个对象也有 length 属性,但它并不是 Array 的实例。

它实际上是基于 DOM 结构动态执行查询的结果,因此 DOM 结构的变化能够自动反映在 NodeList 对象中。我们常说, NodeList 是有生命、有呼吸的对象,而不是在我们第一次访问它们的某个瞬间拍摄下来的一张快照。

可以将 NodeList 对象转换为数组:

//在 IE8 及之前版本中无效

var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);

考虑兼容性:

function convertToArray(nodes){

var array = null;

try {

array = Array.prototype.slice.call(nodes, 0); //针对非 IE 浏览器

} catch (ex) {

array = new Array();

for (var i=0, len=nodes.length; i < len; i++){

array.push(nodes[i]);

}

}

return array;

}

每个节点都有一个 parentNode 属性,该属性指向文档树中的父节点。以及previousSibling

和 nextSibling 属性,指向前一个或者后一个同级节点。

父节点的 firstChild 和 lastChild属性分别指向其 childNodes 列表中的第一个和最后一个节点。节点不存在是均返回null。

在反映这些关系的所有属性当中, childNodes 属性与其他属性相比更方便一些,因为只须使用简单的关系指针,就可以通过它访问文档树中的任何节点。另外, hasChildNodes() 也是一个非常有用的方法,这个方法在节点包含一或多个子节点的情况下返回 true ;应该说,这是比查询 childNodes列表的 length 属性更简单的方法。

所有节点都有的最后一个属性是 ownerDocument ,该属性指向表示整个文档的文档节点,因此可以直接访问文档节点。

虽然所有节点类型都继承自 Node ,但并不是每种节点都有子节点。

对于节点的操作

DOM 提供了一些操作节点的方法。其中,最常用的方法是appendChild() ,用于向 childNodes 列表的末尾添加一个节点。添加节点后, childNodes 的新增节点、 父节点及以前的最后一个子节点的关系指针都会相应地得到更新。 更新完成后, appendChild()返回新增的节点。

如果传入到 appendChild() 中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置。

如果需要把节点放在 childNodes 列表中某个特定的位置上,而不是放在末尾,那么可以使insertBefore() 方法。这个方法接受两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点( previousSibling ) ,同时被方法返回。如果参照节点是null ,则 insertBefore() 与 appendChild() 执行相同的操作

replaceChild() 方法接受的两个参数是: 要插入的节点和要替换的节点。 要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置。

如果只想移除而非替换节点,可以使用 removeChild() 方法。这个方法接受一个参数,即要移除的节点。被移除的节点将成为方法的返回值

cloneNode() ,用于创建调用这个方法的节点的一个完全相同的副本。 cloneNode() 方法接受一个布尔值参数, 表示是否执行深复制。 在参数为 true的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为 false 的情况下,执行浅复制,即只复制节点本身。

上一篇:简单的Flume和hive的结合


下一篇:error: failed to initialize alpm library