DOM1级定义了一个Node接口,该接口是由DOM中的所有节点类型实现。每个节点都有一个nodeType属性,用于表明节点的类型,节点类型在Node类型中有以下几种:
Node.ELEMENT_NODE(1); 元素节点
Node.ATTRIBUTE_NODE(2); 属性节点
Node.TEXT_NODE(3); 文本节点
Node.DOCUMENT_NODE(9); 文档节点
其实还有很多种,但是那些都不是很常用,所以就来理解这其中4种就可以了,我们先来看看节点类型,比如如下代码:
HTML代码如下:
<div> <p>aaaaaa</p> <p>bbbbbb</p> <p>cccccc</p> </div>
JS如下:
var test = document.getElementById("test"); if(test.nodeType === Node.ELEMENT_NODE) { alert(1) }
如上代码在IE8及以下下是不行的,会报错,如下:
因为IE没有公开Node类型的构造函数,因此在IE8-下会有错误,但是我们可以通过数值来比较,比如上面的要比较元素节点的话,我们可以使用1来比较,同理属性节点是2,文本节点是3;如下代码:
var test = document.getElementById("test"); // 下面的所有的浏览器都支持 if(test.nodeType == 1) { alert(1) }
理解nodeName与nodeValue
nodeName保存的是元素的标签名,而nodeValue一般都是null;我们可以看如下代码,没有特殊的说明,HTML代码都是上面的,因此这边就不贴代码了;如下JS代码测试:
var test = document.getElementById("test"); if(test.nodeType == 1) { console.log(test.nodeName); // 打印DIV console.log(test.nodeValue); // 打印null }
理解节点关系
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> </body> </html>
如上代码,我们可以把head和body是html的子元素,同理html是他们的父级元素,那么head和body就是兄弟元素了,那么head及body里面的就是子元素了,我们需要明白的是每个节点都有一个childNodes属性,其保存的是类似数组的元素,其也有length属性,但是他不是数组Array的实例,比如我们可以看看如下测试代码即可:
<div> <p>aaaaaa</p> <p>bbbbbb</p> <p>cccccc</p> </div>
JS代码如下:
var test = document.getElementById("test"); if(test.nodeType == 1) { console.log(test.childNodes); console.log(test.childNodes.length); }
如上代码,在标准浏览器下及IE9+下 第一行打印如下:
[text, p, text, p, text, p, text, item: function]
第二行打印7 长度为7,因为他们把文本节点那个空格也包括进去了,但是在IE8及以下,长度为3,他们不包括文本空格的节点,因此想要统一的话,我们可以编写HTML代码去掉空格,如下HTML代码即可;
<div><p>aaaaaa</p><p>bbbbbb</p><p>cccccc</p></div>
这个问题稍后在仔细考虑,我们现在来看看如何取得子元素,我们可以使用2种方法,第一种是使用中括号[index]索引,第二种是使用item[index]索引,如下代码:
console.log(test.childNodes[1]); // <p>bbbbbb</p>
console.log(test.childNodes.item(1)); // <p>bbbbbb</p>
但是他们并不是数组,我们可以测试下代码即可,如下代码:
console.log(Object.prototype.toString.call(test.childNodes) === "[object Array]");
// false但是我们使其转换为数组,如下代码:
//在IE8 及之前版本中无效
var arrayOfNodes = Array.prototype.slice.call(test.childNodes,0);
console.log(arrayOfNodes instanceof Array);
// true不过在IE8及之前不生效;由于IE8及更早版本将NodeList实现为一个COM对象,而我们不能像使用JScript对象那样使用对象,要想在IE低版本中转换为Array的形式,我们可以像下面一样封装一个方法即可;
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; } var test = document.getElementById("test"); var testArray = convertToArray(test.childNodes); console.log(testArray instanceof Array); // true
理解parentNode(父节点),previousSibling(上一个兄弟节点),nextSibling(下一个兄弟节点);
每个节点都有一个parentNode属性,该属性指向文档中父节点,previousSibling是指当前节点的上一个同胞节点,nextSibling是指当前节点的下一个同胞节点,比如如下代码:
<div><p>aaaaaa</p><p>bbbbbb</p><p>cccccc</p></div> var test = document.getElementById("test"); if(test.nodeType == 1) { var secodeChild = test.childNodes[1]; console.log(secodeChild); // <p>bbbbbb</p> console.log(secodeChild.previousSibling); // <p>aaaaaa</p> console.log(secodeChild.nextSibling); // <p>cccccc</p> }
如果该节点列表中只有一个节点的话,那么该节点的previousSibling和nextSibling都为null;父节点的firstChild指向了父节点中第一个节点;如下代码:
<div><p>aaaaaa</p><p>bbbbbb</p><p>cccccc</p></div>
JS如下: