首页 > 技术文章 > 文档对象模型DOM

zy9731 2017-03-27 10:01 原文

第9章 文档对象模型


DOM简介

① 什么是DOM


所谓DOM,英语全称(Document Object Model),翻译成中文就是文档对象模型。
document对应文档。如果没有文档,也就是没有网页,DOM也就无从谈起。当创建了一个网页并把它加载到web浏览器中时,DOM就悄然而生。浏览器根据网页文档创建一个文档对象。

object对应对象。在JavaScript中对象有三种,如下:
(1)用户自定义对象
(2)内建对象,JavaScript中的对象,如Array,Math,Date等。
(3)宿主对象,由浏览器提供的对象,如window对象。
model对应模型。正如一个火车模型代表一列真正的火车,DOM代表被加载到浏览器窗口里的当前网页。浏览器为我们提供了当前网页的模型,可通过JavaScript去读写它。

② 对DOM的支持
不是所有的浏览器对DOM的支持都一样的,一般来讲火狐对DOM支持最好,几乎支持所有DOM2,以及部分的DOM3。欧朋和safari的支持也比较好,支持最差的就是IE,对DOM1的实现都还不完整。

节点介绍
我们可以把DOM理解为一颗树,树上面有各种各样的节点。不同的节点有不同的节点类型。如下:
元素节点:html标签
文本节点:文本
属性节点:属性总是被包含在标签里,所以属性节点总是被包含在元素节点当中。
如下图:

① 节点类型
DOM本质就是一堆节点的集合,由于包含不同类型的信息,所以就有不同类型的节点。对应属性名nodeType。
元素节点,nodeType为1
属性节点,nodeType为2
文本节点,nodeType为3
文档节点,nodeType为9
注意:文档节点并不是根元素(html),因为注释等内容可以出现在根元素之外。所以在构造DOM树时,根元素并不适合作为根节点,所以就出现了文档节点,而根节点作为文档节点的子节点。


关于属性节点,这里有必要需要强调一点的是属性节点并不是元素节点的子节点,只能算是一个附属节点,先来看一下w3c教程中节点之间的关系

接下来我们可以用实际案例来证明这一点

所以,再次强调,属性节点不是元素节点的子节点,只能算是元素节点的附属节点。

nodeType属性可以和if配合使用,确保不会在错误的节点类型上执行错误的操作。


补充:值和元素类型的对应关系(教材P79)
值:元素类型
1:元素节点,表示文档中元素,元素节点是唯一能够拥有属性的节点类型。元素和属性的文本内容都是由文本节点来表示的。
2:属性节点,代表元素的属性。
3:文本节点,只包含文本内容,也可以只包含空白。
4:CDATA段节点。
5:ENTITY REFERENCE实体引用节点。实体引用节点可以被用于表示DOM树中的一个实体引用。
6:ENTITY实体节点,表示文档中已分析或未分析的实体。
7:PI(processing instruction)处理指令节点,
8:注释节点,表示注释的内容。
9:文档节点(DOCUMENT),文档树的根节点。
10:DOCUMENT TYPE文档类型节点。
11:DOCUMENT FRAGMENT文档片段节点,文档片段是"轻量级的"或"最小的"Document对象。
12:NOTATION记号节点表示了在DTD中声明的记号。
② 节点名称
顾名思义,就是节点的名字,属性名为nodeName
对于元素节点,nodeName就是标签名
对于文本节点,nodeName永远是#text
对于属性节点,nodeName是属性名称
对于文档节点,nodeName永远是#document
注意:
nodeName是一个只读属性,不能进行设置。
nodeName所包含的html元素的标签名称永远是大写的。


③ 节点值
对于元素节点,因为本身不直接包含文本,所以nodeValue是不可用的。
对于文本节点,nodeValue值为文本值
对于属性节点,nodeValue值为属性值


课堂练习:节点介绍综合Demo

④ innerHTML,innerText,value
innerHTML只对元素节点有用,获取元素节点内容,也就是元素节点包含的文本节点的值。其他节点使用nodeValue。

 

还有一个属性叫做innerTest,和innerHTML的区别如下:

由此可见,innerText会把所有内容全部当成元素内容,而innerHTML要更智能一些。

尽管innerHTML对元素节点有用,但不是所有的元素节点都能使用innerHTML获取到里面的内容,比如像<input>元素。

其实很好理解,因为input里面不包含文本节点,所以用innerHTML获取不到文本节点的值。可使用value获取其属性值。
类似的,form里的DOM元素(input select checkbox textarea radio)值获取时都使用value。
textarea虽然可以使用innerHTML获取值,但是获取的是初始文档中的值,当页面的textarea中的值发生变化时,innerHTML不会及时更新。

DOM操作节点
① 访问指定节点
访问指定节点的方法大致有4种
(1)getElementById方法
说明:根据标签的id来查找对应的标签

注意点:如果id值相同,那么就取第一个id匹配上的的标签

(2)getElementsByName方法
说明:通过标签的name属性的值来获取到标签对象,特别适合于用于一组标签的时候

(3)getElementsByClassName方法
说明:返回带有指定类名的所有元素的节点列表。

(4)getElementByTagName方法
说明:根据标签名来获取到标签对象

运行结果:

② 访问相关节点
快速索引:parentNode,childNodes,firstChild,lastChild,previousSibling,nextSibling,document.documentElement,document.body

所谓相关节点,就是指一个节点的父节点,子节点等和本节点相邻的节点
(1)parentNode
就是自己的父节点。


(2)childNodes
说明:childNodes保存子节点的引用,包括空白也在内(除了IE<9)也包括<script>在内。

(3)firstChild和lastChild
就是首尾节点

对于firstChild,对常用的就是访问某个元素的文本内容


(4)previousSibling和nextSibling
分别代表左节点和右节点


(5)特殊入口
访问DOM还有两个特别的入口:document.documentElement和document.body。
document.documentElement代表<html>元素。
document.body代表<body>元素,可以为null,比如在body没有呈现的时候引用就是null。

③ 操作节点
(1)createElement(),createTextNode(),appendChild()
createElement和appendChild方法
说明:createElement方法用于创建一个节点,括号里面填写想要创建的标签的标签名
appendChild方法可以将节点添加到文档里面去
示例:在body里面添加节点

示例:在指定节点下面添加节点


createTextNode()方法就是创建文本节点,示例如下:


(2)removeChild(),replaceChild(),insertBefore()
说明:我们既然能够动态的添加一个节点,那么当然能够动态的删除一个节点,删除节点的方法为removeChild

运行结果:点击删除按钮后结果如下

这里有一个问题,就是当我们需要删除一个节点的时候,需要知道它的父节点,就像上面的案例,我们本来是想删除article1这个节点的,但是我们是从div1这个父节点入手,然后删除article1。
使用parentNode属性,我们可以访问到某个节点的父节点

所以,我们在不知道父节点的id的情况下,也可以删除该节点


语法:replaceChild(新节点,旧节点)
说明:除了创建和删除节点以外,我们还可以对某个节点进行替换


语法:insertBefore(新节点,旧节点)
说明:指定在某个旧节点前面插入一个节点

(3)createDocumentFragment()
说明:刚才我们已经学会了向文档里面添加节点,但是存在一个问题,如果是要添加大量节点的话,这种逐个添加的方法会显得效率很低,因为添加一个节点就会刷新一个页面。这个时候,我们就可以使用createElementFragment方法,将节点先添加在一个文档碎片里面,然后再一次性添加到文档里面。
示例:没有使用createElementFragment方法时,每次都要产生一次页面刷新

示例:使用createElementFragment方法,先将元素添加到文档碎片里面去

运行结果和上面一样,但是页面只会刷新一次,这就是createElementFragment方法的优点。

(4)cloneNode
说明:有些时候我们不想创建和插入一个完全新的元素,而是想复制某个节点,就可以使用这个方法。该方法还可以传入一个布尔值,如果为真,就是深度复制,代表复制某个节点和其子节点,如果为假,就代表仅复制某个节点


(5)createComment()
可创建注释节点, 并插入HTML文档

效果:


DOM操作属性
① 属性操作
快速索引:getAttribute(),setAttribute(),removeAttribute()
用getAttribute(),setAttribute()和removeAttribute()控制HTML标签的属性。
(1)getAttribute方法
说明:得到某个元素的属性

还有一种方法,是通过getNamedItem() 方法返回节点列表中指定属性名的值。


(2)setAttribute方法
说明:设置某个元素的属性

还有一种方法:setNamedItem
setNamedItem() 方法用于添加指定节点。
如果节点已经存在,它将被替换,并返回替换节点的值,否则将返回 null。


(3)removeAttribute方法
说明:移除某个元素的属性

移除同样也用另外一种方法,removeNamedItem()


(4)createAttribute方法
createAttribute()为创建一个属性,如下:


(5)item(pos):item方法可返回节点列表中处于指定索引号的节点。
下面的示例展示了通过item来获取一个元素里面的属性名

② table方法
table对象代表一个html表格
在HTML文档中<table>标签每出现一次,一个table对象就被创建
row[ ]:所有行的数组
cells[ ]:所有单元格的数组

删除一行:deleteRow(index)

插入一行:insertRow(index):只会产生一个tr


其余表格相关方法,见教材P92页。

DOM操作样式
① 操作style属性
(1)写法问题
首先需要注意的就是写法问题,在DOM里面操作样式,属性的写法略有不同。
如下表:
CSS样式 JavaScript样式属性
background-color style.backgroundColor
font-family style.fontFamily
font-weight style.fontWeight
color style.color
cursor style.cursor

(2)obj.style.属性=属性值

obj.style.属性=属性值,是通过添加内联样式去覆盖已有样式的。

 

② 操作外部样式表
document.styleSheet[0].cssRules
③ 操纵最终样式表
(1)IE:currentStyle
(2)DOM:getComputedStyle()

推荐阅读