当前位置: IT培训 > HTML5培训 > 前端开发 > HTML5 > JS之DOM(一)
JS之DOM(一) 时间:2017-05-15     来源:移动互联网学院

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

平台、语言中立的方式。

        1998 年 10 月 DOM1级规范成为 W3C 的推荐标准,为基本的文档结构及查询提供了接口。

 

一、节点层次

        DOM 可以将任何 HTML 或 XML 文档描绘成一个由多层节点构成的结构。节点分为几种不同的类型,每种类型分别表示文档中不同的信息及(或)标记。每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。以下面的HTML为例:

1. <html>

2.    <head>

3.        <title>Sample Page</title>

4.    </head>

5.    <body>

6.        <p>Hello World!</p>

7.    </body>

8. </html>

        其层次结构可表示为:

 

        文档节点是每个文档的根节点。在这个例子中,文档节点只有一个子节点,即<html>元素,我们称之为文档元素。文档元素是文档的外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在 HTML 页面中,文档元素始终都是<html>元素。在 XML 中,没有预定义的元素,因此任何元素都可能成为文档元素。

 

        总共有 12 种节点类型,这些类型都继承自一个基类型。  

 

        A、Node类型

        DOM1 级定义了一个 Node 接口,该接口将由 DOM 中的所有节点类型实现。这个 Node 接口在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)。  

 

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

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

2.    alert("Node is an element.");

3. }

        然而,由于 IE 没有公开 Node 类型的构造函数,因此上面的代码在 IE 中会导致错误。为了确保跨浏览器兼容,好还是将 nodeType 属性与数字值进行比较:

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

2.    alert("Node is an element.");

3. }

        并不是所有节点类型都受到 Web 浏览器的支持。开发人员常用的就是元素和文本节点。

 

        1. nodeName 和 nodeValue 属性

        要了解节点的具体信息,可以使用 nodeName 和 nodeValue 这两个属性。这两个属性的值完全取决于节点的类型。在使用这两个值以前,好是像下面这样先检测一下节点的类型。

1. if (someNode.nodeType == 1){

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

3. }

        nodeName 中保存的始终都是元素的标签名,而 nodeValue 的值则始终为 null;

 

        2. 节点关系

        每个节点都有一个 childNodes 属性,其中保存着一个 NodeList 对象。 NodeList 是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。请注意,虽然可以通过方括号语法来访问 NodeList 的值,而且这个对象也有 length 属性,但它并不是 Array 的实例。 NodeList 对象的独特之处在于,它实际上是基于 DOM 结构动态执行查询的结果,因此 DOM 结构的变化能够自动反映在 NodeList 对象中。我们常说, NodeList 是有生命、有呼吸的对象,而不是在我们第一次访问它们的某个瞬间拍摄下来的一张快照。

        下面的例子展示了如何访问保存在 NodeList 中的节点——可以通过方括号,也可以使用 item()方法。

1. var firstChild = someNode.childNodes[0];

2. var secondChild = someNode.childNodes.item(1);

3. var count = someNode.childNodes.length;

        对 arguments 对象使用 Array.prototype.slice()方法可以将其转换为数组。而采用同样的方法,也可以将 NodeList 对象转换为数组。

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

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

        由于 IE8 及更早版本将 NodeList实现为一个 COM 对象,而我们不能像使用 JScript 对象那样使用这种对象,因此上面的代码会导致错误。要想在 IE 中将 NodeList 转换为数组,必须手动枚举所有成员。下列代码在所有浏览器中都可以运行:

1. function convertToArray(nodes){

2.    var array = null;

3.    try {

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

5.    } catch (ex) {

6.        array = new Array();

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

8.            array.push(nodes[i]);

9.        }

10.    }

11.    return array;

12. }

        每个节点都有一个 parentNode 属性,该属性指向文档树中的父节点。包含在 childNodes 列表中的所有节点都具有相同的父节点,因此它们的 parentNode 属性都指向同一个节点。此外,包含在childNodes 列表中的每个节点相互之间都是同胞节点。通过使用列表中每个节点的 previousSibling和 nextSibling 属性,可以访问同一列表中的其他节点。列表中第一个节点的 previousSibling 属性值为 null,而列表中后一个节点的 nextSibling 属性的值同样也为 null。

1. if (someNode.nextSibling === null){

2.    alert("Last node in the parent’s childNodes list.");

3. } else if (someNode.previousSibling === null){

4.    alert("First node in the parent’s childNodes list.");

5. }

        当然,如果列表中只有一个节点,那么该节点的 nextSibling 和 previousSibling 都为 null。

        父节点与其第一个和后一个子节点之间也存在特殊关系。父节点的 firstChild 和 lastChild属性分别指向其 childNodes 列表中的第一个和后一个节点。其中, someNode.firstChild 的值始 终 等 于 someNode.childNodes[0] , 而 someNode.lastChild 的 值 始 终 等 于 someNode.childNodes [someNode.childNodes.length-1]。在只有一个子节点的情况下, firstChild 和lastChild 指向同一个节点。如果没有子节点,那么 firstChild 和 lastChild 的值均为 null。

 

        另外, hasChildNodes()也是一个非常有用的方法,这个方法在节点包含一或多个子节点的情况下返回 true;应该说,这是比查询 childNodes列表的 length 属性更简单的方法。所有节点都有的后一个属性是 ownerDocument,该属性指向表示整个文档的文档节点。这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于两个或更多个文档中。通过这个属性,我们可以不必在节点层次中通过层层回溯到达顶端,而是可以直接访问文档节点。

X