节点层次
节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。文档节点是每个文档的根节点,文档节点只有一个子节点,
即<html>元素:我们称之为文档元素。文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在html页面中,文档元素始终都是<html>元素。
每一段标记都可以通过树中的一个节点来表示:HTML元素通过元素节点表示,特性通过特性节点表示,文档类型通过文档类型节点表示。
Node类型
每一个节点都有一个nodeType属性,用于表明节点的类型。
元素节点类型:1
特性节点类型:2
文本节点类型:3
注释节点类型:8
文档节点类型:9
通过比较常量,可以确定节点的类型。eg:
<script type="text/javascript">
if(someNode.nodeType == 1){
alert('Node is an element')
}
</script>
要了解节点的具体信息,可以使用nodeName和nodeValue。这两个属性的值完全取决于节点的类型。eg:
<script type="text/javascript">
if (someNode.nodeType == 1){
value = someNode.nodeName //nodeName的值是元素的标签名
}
</script>
对于元素节点,nodeName中保存的始终都是元素的标签名,而nodeValue的值则始终为
null。
节点关系
每个节点都有一个childNodes属性,其中保存着一个NodeList对象。NodeList是一种类数组的对象,用于保存一组有序的节点,可以通过为止来访问这些节点。请注意,虽然可以通过方括号语法来访问NodeList的值,而且这个对象也有length属性,但他并不是Array的实例。Nodelist对象的独特之处在于,它实际上是基于DOM
动态执行查询的而结果,因此DOM结构的变化能够自动反映在NodeList对象中。eg:
<script type="text/javascript">
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNodes.childNodes.length;
</script>
注意:length属性表示的是访问NodeList的那一刻,其中包含的节点数量。对arguments对象使用Array.protype.slice()方法可以将其转换为数组。而采用同样的方法,也可以将NodeList对象转换为数组。eg:
var arrayofNodes = Array.prototype.slice.call(someNode.childNodes,0)
每个节点都有一个parentNodes属性,该属性指向文档树中的父节点。包含在childNodes列表中的所有节点都具有相同的父节点,因此它们的parentNodes都指向了同一个节点。此外,包含在childNodes列表中的每个节点相互之间都是同胞节点。通过使用列表中的每个节点的previousSibling属性和nextSibling属性,可以访问同一列表中的其他节点。
列表中的第一个节点的previousSibling属性值为null,而列表中最后一个节点的nextSibling属性的值也为null。eg:
<script type="text/javascript">
if (someNodes.nextSibling === null){
alert("Last node in the parent's chiladNodes list")
}else if(someNodes.previousSiblin ==- null){
alert("First node in the parent's childNodes list")
}
</script>
如果列表中只有一个节点,那么该节点的nextSibling和previousSibling都为null。父节点与其第一个和最后一个子节点之间也存在特殊关系。父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点。其中,someNode.firstChild的值始终等于 someNode.childNodes[0],而someNodes.lastChild始终等于someNodes.childNodes[someNode.childNodes.length-1].
在只有一个子节点的情况下,firstChild和lastNode指向同一个节点。如果没有子节点,firstNode和lastNode的值均为null。
hasChildNodes( )方法在节点包含一或多个子节点的情况下返回true。是
所有节点都有最后一个属性是ownerDocument,该属性指向整个文档的文档节点。这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在与两个或更多个文档中。
操作节点
appendChild( ),用于向childNodes列表的
末尾添加一个节点。
添加节点后,childNodes的新增节点,父节点及以前的最后一个子节点的关系都会相应的得到更新。更新完成后,appendChild( )返回新增的节点。
var returnNode = someNodes.appendChild(newNode);
alert(returnNode == newNode); //true
alert(someNode.lastChild == newNode); //true
如果需要把节点放在childNodes列表中某个特定的位置上,而不是放在末尾。可以使用insertBefor( )方法
。这个方法接收两个参数:要插入的节点和作为参照物的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回。如果参照节点是Null,则insertBefor( )与appendChild( 执行相同的操作。eg:
<script type="text/javascript">
// 插入后成为最后一个子节点
returnedNode = someNode.insertBefore(newNode,null);
alert(newNode == someNode.lastChild); // true
// 插入后成为第一个子节点
returnNode = someNode.insertBefor(newNode,someNode.firstNode);
alert(returnNode == someNode.firstNode); // true
// 插入到最后一个子节点前面
returnNode == someNode.insertBefor(newNode,someNode.lastChild);
alert(returnNode == someNode.childNodes[someNode.childNodes.length-2]); // true
</script>
移除节点
replaceChild( )方法接收两个参数是:要插入的节点和要替换的节点。要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置。eg:
// 替换第一个子节点
var returnedNode = someNode.replaceChild(newNode,someNode.firstChild);
// 替换最后一个子节点
returnedNode = someNode.replaceChild(newNode,someNode.lastChild);
在
使用replaceChild( )插入一个节点时,该节点的所有关系指针都会从被它替换的节点复制过来。
接管从技术上讲,被替换的节点仍然还在文档中,但它在文档中已经没有了自己的位置。
如果指向移除而非替换节点,可以使用removeChild( )方法。这个方法只接受一个参数,即要移除的节点。被移除的节点将成为方法的返回值。eg:
// 移除第一个子节点
var returnNode = someNode.removeChild(someNode.firstNode);
// 移除最后一个子节点
var returnNode = someNode.removeChild(someNode.lastChild);
与只用repaceChild( )方法一样,通过removeChild( )方法移除的节点仍然为文档所有,只不过在文档
中已经没有了自己的位置。
cloneNode( ),用于创建调用这个方法的节点的一个完全相同的副本。cloneNode( )方法接受一个布尔值
参数。在参数为true的情况下,执行深复制:赋值节点及其整个子节点树;在参数为false的情况下,执行浅复制,
即只复制节点本身。复制后返回的节点副本属于文档所有,但并没有为它指定指定父节点。因此,这个节点副本
就成为了一个孤儿,除非通过appenChild()、insertBefore()、replaceChild()将它添加到文档中去。
normalize( )方法唯一的作用就是处理文档树中的文本节点。
Document类型
JS通过Document类型表示文档。在浏览器中,document对象是HTMLDocument的一个实例,表示整个
HTML页面。而且,document对象是window对象的一个属性,因此可以将其作为全局对象来访。
DOM标准规定Document节点的子节点可以是DocumentType、Element、ProcessingInstruction、
Comment,但还有两个内置的访问其子节点的快捷方式。第一个就是documentElement属性,该属性始终指向
HTML页面中的<html>元素。另一个就是通过childNodes列表访问文档元素,但通过documentElement属性则能
更快捷、更直接地访问该元素。
查找元素
要想取得文档中的所有元素,可以向getElementsByTagName('*')。
只有HTMLDocument类型才有的方法,是getElementsByName(),这个方法会返回带有给定name特性的所
有元素。最常使用该方法的情况是取得单选按钮;为了确保发送给浏览器的值正确无误,所有单选按钮必须具有相同
的name特性。
文档写入
document对象将输出流写入到网页中的能力。write()和writen(),区别在于writen()会在字符串的末尾添加
一个换行符。
Element类型
在HTML中,标签名始终都以全部大写表示。
取得特性
操作DOM方法主要有三个:分别是getAttribute()、setAttribute()、removeAttribute()。如果给定名称的
属性不存在,getAttribute()返回null。
设置特性
与getAttribute()对应的方法是setAttribute(),这个方法接受两个参数:要设置的特姓名和值。如果特性已经存在,setAttribute()会以指定的值替换现有的值;如果特性不存在,setAttribute()则会创建该属性并设置相应的值。
删除特性
removeAttribute(),这个方法用于彻底删除元素的特性。调用这个方法不仅会清除特性的值,而且也会从元素中完全删除特性。
创建元素
使用document.createElement()方法可以创建新元素。这个方法只接受一个参数,即要创建元素的标签名。
Text类型
文本节点的nodeValue的值为节点所包含的文本;不支持(没有)子节点。可以通过nodeValue属性或data属性访问Text节点所包含的文本。
DOM查找总结
document.getElementById()
[document|Element].getElementByClassName()
[document|Element].getElementByTagName()
[document|Element].querySelector()
[document|Element].querySelectorAll()
querySelector()方法
querySelector()方法接受一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。
var body = document.querySelector('body'); //取得body元素
var myDiv = document.querySelector('#myDiv');//取得id为'#myDiv'的元素
var selected = document.querySelector('.selected');//取得类为'selected'的第一个元素
var img = document.querySelector('img.button');//取得类为button的第一个图像元素
querySelectorAll()方法
该方法返回的是 所有匹配的元素而不是仅仅是一个元素。这个方法返回的是一个NodeList的实例。具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的 快照, 而非不断对文档进行搜索的动态查询。
只要传给querySelectorAll()的CSS选择符有效,该方法都会返回一个NodeList对象,而不管找到多少匹配的元素。如果没有找到匹配的元素,NodeList就是空的。
//找到某DIV种的所有em元素
var ems = document.getElementById('myDiv').querySelectorAll('em')
//取得所有p元素中的所有strong元素
var strongs = document.querySelectorAll('p strong')
DocumentFragment
在所有节点类型中,只有DoucumentFragment在文档中没有对应的标记。DocumFragment的nodeType的值为11。虽然不能把
文档片段直接添加到文档中,但可以将它作为一个“仓库”来使用,即可以在里面保存将来会添加到文档中的节点。
文档片段继承了Node的所有方法,通常用于执行那些针对文档的DOM操作。如果将文档中的节点添加到文档片段中,就会从文档树中移除该节点,也不会从浏览器中再看到该节点。添加到文档片段中的新节点同样也不属于文档树。可以通过appendChild()和insertBefore()将
文档片段中的内容添加到文档中。在将文档片段作为参数传递给这两个方法时,实际上只会将文档片段的所有子节点添加到相应的位置上;文档片段本身永远不会成为文档树的一部分。eg:
<script type="text/javascript">
var ul = document.createElement('ul');
document.body.appendChild(ul);
var osList = ['mac','win','linux'];
var frag = document.createDocumentFragment();
for(var i = 0,len = osList.length;i<len;i++){
var li = document.createElement('li');
var liText = document.createTextNode(osList[i]);
li.appendChild(liText);
frag.appendChild(li)
}
ul.appendChild(frag)
</script>