红书第十章 DOM

本章主要讨论与浏览器中HTML页面相关的DOM1级的特性和应用

1 节点层次

DOM将HTML文档或XML文档描绘成一个树形结构,树节点有多种不同类型,代表文档中不同的信息,每个节点都有些自己的属性和方法。

1.1 Node类型

    DOM1级定义了一个Node接口,因为所有节点都是Node,所以所有节点都实现了这个接口。
    在js中,接口作为Node类型实现。所以除了IE外,其它浏览器都能访问到这个Node类。
    Node有nodeType,nodeType的值只能在12种常量里取:ELEMENT_NODE ATTRIBUTE_NODE TEXT_NODE CDATA_SECTION_NODE ENTITY_REFERENCE_NODE ENTITY_NODE PROCESSING_INSTRUCTION_NODE COMMENT_NODE DOCUMENT_NODE DOCUMENT_TYPE_NODE DOCUMENT_FRAGMENT_NODE NOTATION_NODE
    想要判断Node的类型,在除IE以外浏览器可以直接像这样xx.nodeType == Node.ELEMENT_NODE判断,如果是IE浏览器只能判断值,像这样xx.nodeType == 1,因为IE的Node类型不是公开的。
Node属性
    nodeName和nodeValue是两个比较重要的属性。如果一个节点是元素类型,它的nodeName就是这个元素的标签名。
    每个节点都有childNodes属性,里边保存一个NodeList对象。
    NodeList是类数组对象,可遍历,但不是Array实例。NodeList神奇的地方在于,它是基于DOM结构的动态的数据,DOM结构变化,NodeList会同步变化。
    节点还有parentNode属性,指向父节点。
    此外还介绍了些属性,都在下图

pic1.png

    最后讲了ownerDocument属性,指向文档节点。这样无需层层回溯就能访问到元素所属的文档的根节点。
Node方法
    appendChild 向节点的childNodes末尾添加一个节点,添加成功后会返回这个新增的节点。如果添加的节点本来就是文档中的节点,则它会被移到新位置。
    insertBefore 向节点的childNodes特定位置插入节点,参数需要传入参照节点,插入成功后,新节点会作为同胞节点排在参照节点的前面。
    replaceChild 用一个元素替换掉指定元素,传两个参数
    removeChild 移除指定元素
    以上4个方法都要先取得指定节点,才能调用该节点的操作方法。注意不是所有类型的节点都支持childNodes(比如文本节点),在不支持childNodes的节点上调用以上方法会报错。
另外还有:
    cloneNode 复制节点。接收一个布尔型参数,传参为true时深拷贝节点,即其下的子节点也拷贝;传参为false时浅拷贝,即只拷贝节点自身,不会把cildNodes拷贝来。这个方法只会复制特性、子节点(参数为true时),不会复制js属性(比如事件处理程序)。不过IE上有bug,cloneNode会把事件处理程序也复制来。
    normalize 整理树,如果该节点的后代中有相邻的文本节点,就会合并,如果有空的文本节点,就会删除。

1.2 document类型

    js用document表示文档。在浏览器中document是HTMLDocument类的实例,HTMLDocument类继承Document类。
document对象有这些特征:nodeType值为9;nodeName值为“#document”;nodeValue值为null;parentNode的值为null;ownerDocument值为null。
文档的子节点
    document有一个属性叫documentElement,其值与其firstChild值全等,也与childNodes[0]全等。
    document还有个属性叫body。
    document.doctype,这个不常用
文档信息
    document.title页面标题
    document.url地址栏url
    document.domain页面的域名,可以设置,但是不能随便设,只能设置为原url中已经包含的域。页面中嵌有其它子域的页面时,不同frame的js对象由于跨域限制不能通信,可以利用这个设置使不同子域的js对象通信。另外还有个限制,已经设成比较高级的域了,不能再设置成较低级的子域,域只能从低往高改变。
    document.referrer链接到当前页面的原页面url(可能为空)
    以上这几条属性都不是Document类型上定义的,而是作为HTMLDocument实例而带有的属性。
    url、domain、referrer这些在HTTP头部都有,放在document对象上是为了方便js脚本获取这些信息。
查找元素
    document.getElementById 根据id获取元素,参数大小写是区分的。作者还介绍了这个方法在ie8以下版本的略奇特的行为。
    document.getElementsByTagName 返回一个动态集合HTMLCollection,HTMLCollection支持按元素名称查找元素,方法:HTMLCollection对象[名称]或HTMLCollection对象.namedItem(名称)
    document.getElementsByName 这个方法是定义在HTMLDocument类上的,返回的也是HTMLCollection
特殊集合
    document.anchors、applets、forms、images、links 这些属性定义在HTMLDocument类上,都是返回元素集合,也是HTMLCollection,活的。不过这些集合感觉都不会常用。
DOM一致性检测
    document.implementation 用于提供信息,告知开发者浏览器到底实现了哪些DOM功能。向这个方法传入DOM功能名称和版本号(两个字符串),如果浏览器支持,就会返回true。不过有时候浏览器开发者不诚实,没实现的也返回true,所以建议将此方法与别的能力检测方法结合起来使用。
文档写入
    document.write、document.writeln、document.open、document.close
    前两个方法可以向页面写入内容,可以写入各种标签,还可以动态地包含外部资源。页面加载过程中执行write和加载完成后执行write会有不同的结果。open和close方法用于打开和关闭网页的输入流。
    “严格型 XHTML 文档不支持文档写入。对于那些按照 application/xml+xhtml 内容类型提供的页面,这两个方法也同样无效。”     不知道什么是“严格型 XHTML 文档”和“application/xml+xhtml 内容类型”


1.3 Element类型

    Element类型用于表现XML或HTML元素,Element节点具有以下特征:nodeType值为1;nodeName值为元素标签名;nodeValue值为null,parentNode可能是Document可能是Element;子节点可能是Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference。
HTML元素
    HTML元素都继承HTMLElemnt类型(或者其子类),HTMLElement类型则继承Element类。HTMLElement比Element类多了些以下属性:id、title、lang(元素的语言)、dir(元素的文本方向)、className(元素的css类名)。这些属性可用js代码读取,也可以用js去修改。
    然后作者罗列了HTMLElement类的子类,就不抄了。

取得特性
    讲了getAttribute、setAttribute、removeAttribute方法
    直接访问DOM元素属性也能读取、修改属性。它们的区别在于,getAttribute可以访问自定义的元素属性(通常前面会加data-),而直接访问DOM元素属性只能访问原先就有的非自定义的属性(除了ie)。

设置特性
    setAttribute可以操作DOM元素原生特性也可以操作自定义的特性,用setAttribute方法设置的特性名会被转换成小写。
    removeAttribute可以删除元素特性

attributes属性
    Element类型独有的属性:attributes。
    element.attributes是一个动态的集合,包含一系列节点,每个节点的nodeName就是特性名称,节点的nodeValue就是特性值。
    element.attributes的getNamedItem、removeNamedItem、setNamedItem、item(pos)可以取、删、增元素属性。比如:element.attributes.getNamedItem('id')可取得元素id。一般来说,需要将DOM结构序列化为XML或HTML字符串时,会用attributes来遍历元素特性。

创建元素
    document.createElement(标签名)可以创建新元素,在ie中可以document.createElement(完整的包含元素属性的字符串)

元素的子节点
    element.childNodes会返回元素的子节点。这个方法不同浏览器会有差异,ie不把空白符算作一个节点,其它浏览器会。
    element.getElementsByTagName可以取得元素后代中的指定元素

1.4 Text类型

text类型节点具有以下特征:
    nodeType为3
    nodeName为#text
    nodeValue为节点文本值
    data属性为节点文本值
    parentNode是一个Element
    不支持子节点
    appendData(文本)可以把文本追加到节点的末尾、
    deleteData(offset, count)可以从offset位开始删掉count个字符
    insertData(offset, text)在offset位插入text
    replaceData(offset, count, text)从offset位开始到offset+count位为止的文本替换成text
    splitText(offset)在offset位把文本分成两个文本节点
    substringData(offset, count)读取从offset位置开始到offset+count为止的字符串
    length文本节点里内容长度
创建文本节点
    document.createTextNode可以创建文本节点
规范化文本节点
    element.normalize可以把元素下的相邻文本节点合并到一起。一般出现相邻文本节点是执行DOM操作的结果,浏览器解析文档时不会没事把字符串拆成多个相邻的文本节点。
分割文本节点
    Text节点的splitText方法,会把一个文本节点分割成两个相邻的文本节点。

1.5 Comment类型

    Comment类型节点具有以下特征:nodeType值为8、nodeName值为#comment、nodeValue值为注释的内容、parentNode可能是Document也可能是Element、不支持子节点
    Comment与Text继承自相同的基类,Comment除了splitText方法外,其它Text类有的操作方法它都有。
document.createComment方法可以创建注释节点
注意:浏览器不会识别之后的注释,Comment节点只有作为html元素的后代元素,才能被浏览器识别。

1.6 CDATASection类型

    CDATASection类型只针对基于XML的文档,表示的是CDATA区域。

1.7 DocumentType类型

    DocumentType类型节点包含与文档doctype有关的所有信息,其nodeName的值为doctype的名称。DocumentType节点不能动态创建,只能通过解析文档的方式创建,浏览器(如果支持它的话)会把它放在document对象的doctype属性中。

1.8 DocumentFragment类型

    DocumentFragment节点在文档中没有对象的标记,它继承了Node的所有方法,可以进行DOM操作。
    DocumentFragment是文档片段,可以包含和控制节点,但不会像完整文档那样占用额外的资源。
文档片段的用途是作为一个“仓库”,在仓库里创建修改节点,然后添加到文档树,也可以把文档树上的节点移到仓库。

1.9 Attr类型

    元素的特性在DOM中以Attr类型节点来表示,特性就是存在于元素的attributes属性中的节点。
    有3个属性,name(特性名称)、value(特性值,与节点nodeValue相同)、specified(布尔值,是代码指定的属性还是默认的属性)
    document.createAttribute可以创建特性节点。然后传递给element.setAttributeNode即可把特性添加到元素上。


2 DOM操作技术

2.1动态脚本

    向页面插入JavaScript代码,插入的script标签可以本身就包含代码,也可以用src从外部引入。当script标签被添加到文档树之后,开始运行。

2.2动态样式

    可以动态创建元素或