DOM介绍

1. 概念

    DOM(文档对象模型)是针对HTML和XML的一个API(应用程序编程接口)。

    1998年10月DOM1级规范成为W3C的推荐标准。

    本章主要讨论与浏览器HTML页面相关的DOM1级特性和应用,以及JavaScript对DOM1级的实现。

    注意:IE中的所有DOM对象都是以COM对象的形式实现的,所以很多DOM行为跟其他浏览器不一致

2.  节点层次

    文档节点<document>是每一个文档的根节点。

    文档节点的子节点可以有文档类型节点(如<!DOCTYPE>)、元素节点(如<html>)、注释节点(如<!--注释-->)这三种类型。其中在HTML页面中<html>称之为文档元素,包含了其他所有元素。

2.1 Node类型

    DOM的节点类型有12种,但都是继承自DOM1定义的Node接口,在JavaScript中用同名的Node类型实现,所有节点都是继承自Node类型,所以所有的节点类型会有一些共有的属性和方法。注意:除了在IE中,其他浏览器都可以访问Node类型。

2.1.1 共有的属性和方法

  • nodeType
  • nodeName
  • nodeValue
  • ownerDocument
  • hasChildNodes()
  • cloneNode()
  • normalize()

    nodeType表示节点的类型,Node类型定义了12种节点类型的常量值,如下:

  1. Node.ELEMENT_NODE(1) //元素节点
  2. Node.ATTRIBUTE_NODE(2) //属性节点
  3. Node.TEXT_NODE(3) //文本节点
  4. Node.CDATA_SECTION_NODE(4)
  5. Node.ENTITY_REFERENCE_NODE(5)
  6. Node.ENTITY_NODE(6)
  7. Node.PROCESSING_INSTRUCTION_NODE(7)
  8. Node.COMMENT_NODE(8) //注释节点
  9. Node.DOCUMENT_NODE(9) //文档节点,根节点
  10. Node.DOCUMENT_TYPE_NODE(10) //文档类型节点
  11. Node.DOCUMENT_FRAFGMENT_NODE(11)
  12. Node.NOTATION_NODE(12) //符号节点

    其中,括号中的数值即对应类型在nodeType中的数值表示

    再次提醒,IE中没有公开Node类型的构造函数,因此Node的常量值在IE中是会报错的,这时候使用括号中的数值表示是最合适的,如

 
/*检查节点的类型*/
if (someNode.nodeType == 1) { //适用于所有浏览器
   console.log("this node is an element");
}

    nodeName表示节点名字,如果是元素节点,则直接给出标签名(大写形式),例如:

<!--nodeName-->
<!DOCTYPE html>
<html>
</html>
 
var commentNode = document.childNodes[0];
var docTyoeNode = document.childNodes[1];
var elementNode = document.childNodes[2];
commentNode.nodeName; //#comment
docTypeNode.nodeName; //html
elementNode.nodeName; //HTML

    nodeValue在元素节点中值为null,其他类型节点尚且没去研究。

    ownerDocument指向文档节点<document>,让任何节点都可以直接访问其文档节点。

    hasChildNodes(),没有参数;有一个或者多个子节点则返回true,否则返回false。该方法用于查看是否有子节点。

    cloneNode(isDeep),参数是true/false,表示是否深复制;返回复制的节点。该方法用于复制某个节点。

    当参数为true,表示深复制,将复制该节点及其整个子节点树;当参数为false,则只复制该节点。

    normalize(),用于处理文档树种的文本节点。调用该方法,将查询该节点的后代节点是否有空文本节点,有则删除它;是否有相邻的文本节点,有则将它们合并为一个文本节点。

2.1.2 其他属性和方法

  • childNodes
  • parentNode
  • firstNode
  • lastNode
  • previousSibling
  • nextSibling

    所有的元素节点都有以上属性,但是不是所有节点类型都有

    childNodes保存着所有子节点的引用,是一个NodeList对象(类数组对象,按序保存存储所有子节点)

    NodeList是对DOM结构动态查询的结果,即具有实时性;访问NodeList中的元素可以使用方括号,可以用特有的item()方法,如下:

var firstNode = someNode.childNodes[0]; //第一个子节点,括号形式更常用
var length = someNode.childNodes.length; //子节点个数
var lastNode = someNode.childNodes.item(length - 1); //最后一个子节点

    parentNode直接指向父节点。

    firstNode和astNode分别指向第一个子节点和最后一个子节点。

    previousSibling和nextSibling分别表示指向上一个兄弟节点和下一个兄弟节点(同胞节点)

2.1.3 常用操作节点的方法

  • appendChild()
  • insertBefore()
  • replaceChild()
  • removeChild()

    appendChild(newNode)参数是新增的节点;返回值是新增的节点。该方法用于向childNodes列表的末尾添加一个节点。

    注意:如果参数node是文档中已经存在的节点,则将该节点从原来的位置转移到childNodes列表末尾。

    insertBefore(insertNode, referNode),参数1是要插入的节点,参数2是参照节点;返回要插入的节点。该方法用于调整节点的位置,将插入节点插入到参照节点的前面,成为其同胞节点,但是以下操作则成为子节点:

/*插入后成为最后一个子节点,等同于appendChild*/
returnNode = insertBefore(insertNode, null); 
/*插入后成为第一个子节点*/
returnNode = insertBefore(insertNode, someNode.firstNode);

    replaceChild(insertNode, replaceNode),参数1是要插入的节点,参数2是被替换的节点;返回被替换的节点。该方法用于替换某个节点。

    removeChild(removeNode),参数是被移除的节点;返回被移除的节点。该方法用于移除某个节点。

    注意:

 

  1. repalceChild()和removeChild()方中被替换和移除的节点仍然存在文档中,只是没有了位置,仍然可以使用引用。
  2. 这些操作方法都基于操作子节点,若没有子节点的节点类型使用这些操作方法,则会报错。

2.2 Document类型

    Document类型可以表示HTML或XML的文档。

    在JavaScript中用同名Document类型来表示文档。

    在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面,同时也是window对象的一个属性对象,可作为全局对象使用。

    文档节点<document>有以下特性:

 

  1. nodeType值为9
  2. nodeName值为"#document"
  3. parentNode、nodeValue、ownerDocument值为null
  4. 子节点类型只能是文档类型节点(最多一个)、元素节点(如<html>,最多一个)、ProcessingInstruction或者注释节点(可以有多个)

2.2.1 获取文档的子节点

    前文已经两次介绍文档节点子节点的类型,这里不赘诉。

    DOM标准规定中内置有访问文档节点的子节点的快捷方式,两个属性是(所有浏览器都支持):

  • documentElement
  • body

    documentElement直接指向文档中<html>元素节点。

    body直接指向文档中<body>元素节点。

    另外一个属性是doctype(使用较少),doctype直接指向文档中的文档类型节点。浏览器支持情况如下:

  1. IE8及之前版本,该属性值为null,并且会将文档类型节点当成一个注释节点。
  2. IE9+、FireFox及Chorme,该属性值为第一个文档类型节点,同时会将文档节点作为第一个子节点。

2.2.2 获取文档信息

    document对象以下属性存储着文档的信息:

  • title
  • URL
  • domain
  • referrer
var title = document.title; //获取文档标题
title = "test title of document"; //设置文档标题

/*与网页请求相关的属性*/
var url = document.URL; //获取完整的URL
var domain = document.domain; //获取域名
var referrer = document.referrer; //获取上一个页面的url

    注意:与网页请求相关的三个属性其实都取值自HTTP报头部,用于我们方便在js中访问(location对象也有类似属性可以使用)

2.2.3 获取元素

    document对象提供了获取文档中元素的方法:

  • getElementById()
  • getElementsByTagName()
  • getElementsByName()
  • getElementsByClassName()

    前两个方法是Document类型规定给出的方法,后两个是HTMLDocument特有的方法。

    getElementByID(id),参数是元素节点的id值;返回匹配的元素。

    注意:

  1. 这里ID属性区别大小写,但是IE8-不区分ID属性的大小写
  2. 当有多个相同的ID值匹配时,返回第一个匹配的元素

    getElementsByTagName(tagName),参数是元素的标签名;返回一个HTMLCollection对象(与NodeList对象特性类似),保存着匹配的元素集合,访问对象中元素的方法如下:

var images = document.getElementsByTagName("img");
console.log(images[0].src); //查看第一张图片的src,方括号方法
console.log(images.item(0).src); //item()方法
console.log(images.namedItem("apple")); // 通过name属性匹配,该对象特有的
console.log(images.length); //集合的大小

/*获取文档中所有元素*/
var elments = document.getElementsByTagName("*"); //在IE中注释节点会被解释成元素,所以也会返回

    getElementsBy(name),参数是元素的name属性值;返回一个HTMLCollection对象。常用于表单。

    getElementsByClassName(className),参数是元素的class属性值;返回一个HTMLCollection对象。

    注意:

  1. getElementsByTagName()不区分大小写,但是在XHTML中会区分大小写。    
  2. 后两个方法访问对象中元素的方法参照getElementsByTagName()

2.2.4 特殊的属性集合

    document对象还提供了一些特殊的属性,这些属性都是HTMLCollection对象,用以快速的访问文档中的元素,包括:

  • anchors,包含文档中所有带name属性的<a>元素
  • forms,包含文档中所有的<form>元素
  • images,包含文档中所有的<img>元素
  • links,包含文档中所有带href属性的<a>元素

2.2.5 DOM一致性检测

    检查浏览器实现的DOM级别,通过document.implementation可以查看,查看方法:

  • document.implementation.hasFeature()

    hasFeature(domFunc, ver),参数1是要检查的DOM功能,参数2是该功能的版本号;若浏览器支持给定的功能和版本号则返回true。例子如:

var hasXmlDom = document.implementation.hasFeature("XML", "1.0");

    考虑到hasFeature()方法并不能一定保证检查的结果,所以为了检测浏览器的功能,还是要进行能力检测(查看客户端检测章节)

2.2.6 文档写入

    document对象还有一个重要的功能,就是将输出流写入到网页中。相关的方法有:

  • write()
  • writeln()
  • open()
  • close()

    方法功能一眼就能明白,下面说两个例子:

/*通常要为写入的文档创建一个标签包裹起来,方便后面对其进行操作*/
document.write("<div id = 'newText'>smash boom boom</div>");

/*动态引入js文件注意要使用转义字符"\",否则会与第一个<scirpt>标签匹配而结束>*/
<script type="text/javascript">
   document.write("<script><\/script>")
</script>

2.3 Element类型

    Element类型是Web编程中另外一个常用的类型,提供了对元素标签名、子节点及特性的访问。

2.3.1 元素属性和特性的区别和联系

    有在HTML页面中出现的和通过setAttribute()设置的都属于特性(Attribute)。

    一些公认的、常用的特性以及通过字面量设置的(如div.color = "red")都属于属性(property)。

    有些常用的特性如id、class、title、stytle、onclick等会在DOM对象中存储对应的属性,即这部分既是特性也是属性。可以说它们是”脚踏两条船“了。同时,它们在特性和属性的值会保持同步。

    还有一个区别是,特性的名称是不区分大小写的。根据HTML5规范,自定义特性应该加上data-前缀。

2.3.2 获取标签名

    除了nodeName,Element类型还有与其一样效果的属性:

 

  • tagName

    主要是为了在元素操作时更清楚的表示标签名。

    注意:这两者在HTML中返回值都是大写,而在XML、XHTML中则返回与源代码保持一样的大小写形式,因此,在检测的时候最好是对获取到的标签名进行大小写转换,如:

if (element.tagName.toLowerCase == "div") {
   alert("this element is a div")
}

    另外,除了IE8-和safari2-外,所有浏览器都可以访问Element类型的原型和构造函数。

2.3.3 元素特性属性的获取和设置

    所有的HTML元素都属于或者继承自HTMLElement类型。

    设置属性的方法:

/*通过"."属性名字面量直接赋值*/
element.propertyName = antType

    这种设置的属性不会有对应的特性生成,因此不能通过getAttribute()获得。

    访问属性同理,注意属性值可以是任何类型。

    有关特性的有三个方法:

 

  • setAttribute()
  • getAttribute()
  • removeAttribute()

    这三个方法可以应用于任何特性(包括自定义属性),同时传入的参数和返回值都是字符串类型。特性的介绍看前文。

    setAttribute(atrName, atrValue):参数1是特性名(如果是大写会被转换成小写形式),参数2是特性值;无返回值。用于设置元素的特性。

    getAttribute(atrName):参数是特性名;返回特性值。用于获取元素的特性。

    removeAttribute(atrName):参数是特性名;无返回值。用于删除元素的特性。IE6-不支持该方法。

    HTMLElement属性中既是属性又是特性的有:

  • id
  • title
  • class
  • style
  • onclick

    其中class特性对应的是className属性,这是由于在ESMAScript中class是保留字。

    由于style和onclick的属性值分别是CSSStyleDeclaration对象和JS函数,而通过getAttribue()方法获得的都是字符串形式(除了IE7-)。

    因此,由于存在以上差异,简单粗暴总结一下:

 

  1. 一般情况下直接使用元素对象的属性,即用"."属性名方式。
  2. 当需要获取自定义特性时使用getAttribute(),即html页面元素中非公认特性的特性,嗯!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值