DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的结构。
节点的特点:节点分为几种不同的类型,每种类型分别表示文档中不同的信息及(或)标记。每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。
文档节点是每个文档的根节点,文档节点只有一个子节点,即html元素,我们称之为文档元素。文档元素是文档的最外层元素,每个文档只能有有一个文档元素。
DOM1
DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。这个Node的接口在JavaScript中是作为Node类型实现的;除了IE之外,在其他所有浏览器中都可以访问到这个类型。JavaScript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。
1、每个节点都有一个nodeType属性,要了解节点的具体信息,可以使用nodeName和nodeValue这两个属性。
2、每个节点都有一个childNodes属性,其中保存着一个NodeList对象。Nodelist是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点([i]或item(i)表示)。
PS:与childNodes表示类似意思的属性:
a、Element Traversal API为DOM元素添加了以下5个属性:1、childElementCount返回子元素的个数,不包括文本节点和注释;2、firstElementChild、firstElementChild、lastElementChild、previousElementSibling、nextElementSibling。
b、由于IE9之前的版本与其他浏览器在处理文本节点中的空白符有差异,因此就出现了children。这个属性是HTMLCollection的实例,只包含元素中同样还是元素的子节点。除此之外,children属性与childNodes没有什么区别。
3、每个节点都有一个parentNode属性,该属性指向文档树种的父节点。
4、通过列表中每个节点的previousSibling和nextSibling,可以访问childNodes中同一列表中的其他节点。
5、父节点与其第一个和最后一个子节点之间也存在特殊关系。父节点的firstChild和lastChild属性分别指向其childNodes列表中的第一个和最后一个节点。
6、hasChildNodes()也是一个非常有用的方法,这个方法在节点包含一或多个子节点的情况下返回true。
7、Selectors API 的核心是两个方法:querySelector()和querySelectorAll()。
querySelector()方法接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。
querySelectorAll()方法接收的参数与querySelector()方法一样,都是一个CSS选择符,但返回的是所有匹配的元素而不仅仅是一个元素。这个方法返回的是一个NodeList实例。具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现类似于一组元素的快照,而非不断对文档进行搜索的动态查询,避免使用NodeList对象通常会引起的大多数性能问题。
DOM2级
定义了两个用于辅助完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。
NodeIterator类型可以使用document.createNodeiterator()方法来创建它的新实例。用法详见Page328(《JavaScript高级程序设计》)
TreeWalker是NodeIterator的一个更高级的版本,可以使用document.createTreeWalker()方法来创建它的实例。TreeWalker真正强大的地方在于能够在DOM结构中沿任何方向移动。例如,TreeWalker类型还有一个属性,名叫currentNode,表示任何遍历方法在上一次遍历中返回的节点。通过设置这个属性可以修改遍历继续进行的起点。详见Page331(《JavaScript高级程序设计》)
节点类型
i、document节点
JavaScript通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面。而且,document对象是window对象的一个属性,因此可以将其作为全局对象来访问。
Document节点具有以下特征:
nodeType == 9;nodeName == "#document" ;nodeValue == null;
Document节点的两个常见的特殊子节点:Document有两个内置的访问其子节点的快捷方式:1、document.documentElement === document.childNode[0],都指向html。2、document对象还有一个body对象,指向body元素。document.body === body,该元素使用频率很高。所有浏览器都支持这两个属性。
document对象所具有的一些特殊的属性:
1、title。document.title
2、URL(完整的链接)、domain(域名)、referrer。Page256,没看懂。
document对象所具有的一些特殊的对象集合:
1、document.anchors,document.applets,document.forms,document.images,document.links
ii、Element节点
Element类型用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问。
1、nodeType === 1,nodeName == "tagName",nodeValue == null;在HTML中,tagName标签名始终都以全部大写表示,转为小写可用toLowerCase()方法。
(1)、HTML元素
HTML元素都由HTMLElement类型表示,可直接通过这个类型,也可通过它的子类型来表示。HTMLElement类型直接继承自Element并添加了一些属性。添加的这些属性分别对应每个HTML元素中都存在的下列标准特性:1、id;2、className;3、title等(lang、dir)。
(2)、取得特性
每个元素都有一或多个特性,这些特性的用途是给出相应元素或其内容的附加信息。操作DOM方法主要有三个,分别是getAttribute()、setAttribute()、removeAttribute()。这三个方法可以针对任何特性使用,包括那些以HTMLElement类型属性的形式定义的特性。
任何元素的所有特性,也都可以通过DOM元素本身的属性来访问。当然,HTMLElement也会有5个属性与相应的特性一一对应。只有公认(非自定义)的特性特性才会以属性的形式添加到DOM对象中。比较特殊的特性是“style”和类似onclick这样的事件处理程序。
(3)、attributes属性
Element类型使用attributes属性的唯一一个DOM节点类型,attribute属性中包含一个NamedNodeMap,与NodeList类似,也是一个“动态”的集合。元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。
attributes属性中包含一系列节点,每个节点的nodeName就是特性的名称,而节点的nodeValue就是特性的值。
(4)、元素的子节点
元素可以有任意数目的子节点和后代节点,元素的childNodes属性中包含了它的子节点,这些子节点有可能是元素、文本节点、注释或处理指令。
iii、Text节点
文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容。
特征:nodeType == 3;nodeName == "#text";nodeValue == “节点所包含的文本”。
文本内容可以通过nodeValue属性或者各种data方法修改。
文本节点还有一个length属性,保存着节点中字符的数目。而且,nodeValue.length和data.length中也保存着同样的值。
D、DocumentFragment节点
在所有节点类型中,只有DocumentFragment在文档中没有对应的标记。DOM规定文档片段是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用额外的资源。
特征:nodeType == 11;nodeName == "#document-fragment";nodeValue == null;
用法:虽然不能把文档片段直接添加到文档中,但可以将它作为一个“仓库”来使用,即可以在里面保存将来可能会添加到文档中的节点。要创建文档片段,可以使用document.createDocumentFragment()方法。
文档片段继承了Node的所有方法,通常用于执行那些针对文档的DOM操作。
操作节点
1、操作节点最常用的方法是appendChild(),用于向childNodes列表的末尾添加一个节点。如果传入到appendChild()中的节点已经是文档的一部分,那结果就是将该节点从原来的位置转移到新位置。
2、如果需要把节点放在childNodes列表中某个特定的位置上,而不是放在末尾,那么可以使用insertBefore(),替换节点的方法:replaceChild(),删除节点removeChild()。这四种方法都是操作某个节点的子节点,使用时必须先取得父节点(parentNode属性)。另外,并不是所有类型的节点都有子节点。
3、有两个方法是所有类型的节点都有的。第一个就是cloneNode(),用于创建调用这个方法的节点的一个完全相同的副本。
取得元素的操作:getElementById()和getElementsByTagName()。getElementsByTagName()返回的是包含零个或多个元素的NodeList。在HTML文档中,这个方法会返回一个HTMLCollection对象。作为一个“动态”集合,该对象与NodeList非常相似。与NodeList对象类似,可以使用[i]或item(i)访问。对于有name特性的元素,可以通过namedItem("nameValue")访问。
对于HTMLCollection而言,我们可以向方括号中传入数值或字符串形式的索引值。在后台,对于数值索引就会调用item(),而对字符串索引就会调用namedItem()。
4、创建元素:document.createElement()方法
5、HTML5添加的新方法:getElementsByClassName(),返回带有指定类的所有元素的NodeList。
DOM级别检测
document.implementation.hasFeature("XML","1.0");
5、创建文本节点:document.createTextNode()创建新文本节点
理解NodeList及其近亲NamedNodeMap和HTMLCollection,是从整体上透彻理解DOM的关键所在。(???)