DOM1
Ⅰ 基本概念
DOM1级于1998年10月成为W3C的推荐标准
DOM1级由两个模块组成:DOM核心(DOM Core)和DOM HTML
DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现,这个Node接口在JavaScript中是作为Node类型实现的;除了IE之外,在其他所有浏览器中都可以访问到这个类型,JavaScript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法
Ⅱ 节点类型
每个节点都有一个nodeType属性,用于表明节点的类型。节点类型由在Node类型中定义的下列12个数值常量来表示,任何节点类型必居其一
节点类型 | 数值常量 | 字符常量 |
Element 元素节点 | 1 | Node.ELEMENT_NODE |
Attr 属性节点 | 2 | Node.ATTRIBUTE_NODE |
Text 文本节点 | 3 | Node.TEXT_NODE |
Cdata 区域节点 | 4 | Node.CDATA_SECTION_NODE |
EntityReference 实体引用节点 | 5 | Node.ENTITY_REFERENCE_NODE |
Entity 实体节点 | 6 | Node.ENTITY_NODE |
ProcessingInstruction 处理指令节点 | 7 | Node.PROCESSING_INSTRUCTION_NODE |
Comment 注释节点 | 8 | Node.COMMENT_NODE |
Document 文档节点 | 9 | Node.DOCUMENT_NODE |
DocumentType 文档节点类型 | 10 | Node.DOCUMENT_TYPE_NODE |
DocumentFragment 文档片段节点 | 11 | Node.DOCUMENT_FRAGMENT_NODE |
Notation DTD 中声明的符号 | 12 | Node.NOTATION_NODE |
由于早期的IE没有公开Node类型的构造函数,意味着在JavaScript中不支持节点类型,在如下的案例中将 someNode.nodeType 与 Node.ELEMENT_NODE 作比较
if (someNode.nodeType == Node.ELEMENT_NODE){ //在IE中无效
alert("Node is an element.");
}
如果二者相等,则意味着someNode确实是一个元素,然而在IE中确是会导致错误,为确保跨浏览器兼容,最好还是将nodeType属性与数字值进行比较,并不是所有节点类型都受到Web浏览器的支持
if (someNode.nodeType == 1){ //适用于所有浏览器
alert("Node is an element.");
}
nodeName和nodeValue属性
在JavaScript中最常用的有 Element(元素节点)、Text(文本节点)、Attribute(属性节点)、Document(文档节点),要深入了解节点的具体信息,可以使用nodeName和nodeValue这两个属性
nodeName 和 nodeValue 属性的值完全取决于节点的类型
nodeName 属性含有某个节点的名称,nodeType 属性可返回节点的类型
nodeName 属性
元素节点的 nodeName 是标签名称(返回的名称是大写的)
属性节点的 nodeName 是属性名称(返回的名称是大写的)
文本节点的 nodeName 永远是 #text
文档节点的 nodeName 永远是 #document
注解:nodeName 所包含的 XML 元素的标签名称永远是大写的
nodeValue 属性
元素节点的 nodeType 常量值是 1
属性节点的 nodeType 常量值是 2
文本节点的 nodeType 常量值是 3
注释节点的 nodeType 常量值是 8
文档节点的 nodeType 常量值是 9
Ⅲ 节点关系
每个节点都有一个childNodes属性,其中保存着一个NodeList对象
NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点
NodeList对象是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反映在NodeList对象中
每个节点都有一个parentNode属性,该属性指向文档树中的父节点
包含在childNodes列表中的所有节点都具有相同的父节点,因此它们的parentNode属性都指向同一个节点
包含在childNodes列表中的每个节点相互之间都是同胞节点
每个节点的previousSibling和nextSibling属性,可以访问同一列表中的其他节点
列表中第一个节点的previousSibling属性值为null,而列表中最后一个节点的nextSibling属性的值同样也为null
如果列表中只有一个节点,那么该节点的nextSibling和previousSibling都为null
if (someNode.nextSibling === null){
alert("Last node in the parent’s childNodes list.");
} else if (someNode.previousSibling === null){
alert("First node in the parent’s childNodes list.");
}
父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点
其中,someNode.firstChild的值始终等于someNode.childNodes[0],而someNode.lastChild的值始终等于someNode.childNodes [someNode.childNodes.length-1]
在只有一个子节点的情况下,firstChild和lastChild指向同一个节点。如果没有子节点,那么firstChild和lastChild的值均为null
通过childNodes属性可访问文档树中的任何节点
通过hasChildNodes()方法,可在节点包含一或多个子节点的情况下返回true,可用此方法查询子节点是否存在
所有节点都有的最后一个属性是ownerDocument
ownerDocument 属性指向表示整个文档的文档节点,这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于两个或更多个文档中,通过这个属性,我们可以直接访问文档节点
Ⅳ 操作节点
appendChild()
用于向childNodes列表的末尾添加一个节点;添加节点后 childNodes的新增节点、父节点及以前的最后一个子节点的关系指针都会相应地得到更新,更新完成后 appendChild()返回新增的节点
var ul = document.getElementsByTagName("ul"),
list = document.getElementsByClassName("list");
// 创建节点
var newLi = document.createElement("li"),
textNode=document.createTextNode("This is fourth li");
// 向UL列表最后一个Li元素追加
newLi.appendChild(textNode);
list[0].appendChild(newLi);
insertBefore()
如果需要把节点放在childNodes列表中某个特定的位置上,可以使用insertBefore() 方法
insertBefore() 方法接受两个参数:要插入的节点和作为参照的节点,插入节点后,被插入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回
如果参照节点是null,则insertBefore()与appendChild()执行相同的操作
var ul = document.getElementsByTagName("ul"),
list = document.getElementsByClassName("list")[0];
// 创建节点
var newLi = document.createElement("li"),
textNode = document.createTextNode("This is fifth li");
// 指定位置追加节点
newLi.appendChild(textNode)
list.insertBefore(newLi,list.childNodes[0])
replaceChild()
replaceChild()方法接受的两个参数是:要插入的节点和要替换的节点,要替换的节点将由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置
var ul = document.getElementsByTagName("ul"),
list = document.getElementsByClassName("list")[0];
// 创建节点
var newLi = document.createElement("li"),
textNode = document.createTextNode("This is sixth li");
// 替换节点
newLi.appendChild(textNode)
list.replaceChild(newLi,list.childNodes[1]);
removeChild()
移除节点,可以使用removeChild()方法,这个方法接受一个参数,即要移除的节点,被移除的节点将成为方法的返回值
var ul = document.getElementsByTagName("ul"),
list = document.getElementsByClassName("list")[0];
// 删除节点
list.removeChild(list.childNodes[1]);
cloneNode()
cloneNode()方法是所有类型的节点都有的,用于创建调用这个方法的节点的一个完全相同的副本
cloneNode()方法接受一个布尔值参数,表示是否执行深复制,在参数为true的情况下执行深复制也就是复制节点及其整个子节点树,需注意的是文档结构中不能有空格换行出现;在参数为false的情况下执行浅复制即只复制节点本身
复制后返回的节点副本属于文档所有,但并没有为它指定父节点,因此这个节点副本就成为了一个"孤儿",除非通过appendChild()、insertBefore()或replaceChild()将它添加到文档中
var myListA = document.getElementById("myListA"),
myListB = document.getElementById("myListB");
var lastChild = myListB.lastChild,
cloneNodes = lastChild.cloneNode(true);
myListA.appendChild(cloneNodes);
normalize()
normalize()方法是所有类型的节点都有的,唯一的作用是处理文档树中的文本节点
由于解析器的实现或DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况
<div class="box">
<p id="text"></p>
<button onclick="addTextNode()">添加一个文本节点</button>
<button onclick="normalParag()">规格化段落</button>
<p>段落有 <span id="textNumber">1</span>子节点</p>
</div>
当在某个节点上调用normalize()方法时,就会在该节点的后代节点中查找上述两种情况。如果找到了空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点
function addTextNode(){
var text = document.getElementById("text");
var textNumber = document.getElementById("textNumber");
var addText = document.createTextNode(" Click on me again ");
text.appendChild(addText);
textNumber.innerHTML = text.childNodes.length;
}
function normalParag(){
var text = document.getElementById("text");
var textNumber = document.getElementById("textNumber");
var addText = document.createTextNode(" Click on me again ");
text.normalize();
textNumber.innerHTML=text.childNodes.length;
}