详解DOM1级与节点类型

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;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值