使用DOM操纵HTML文档几点粗浅认识
来源:互联网 发布:删除有条件的数据sql 编辑:程序博客网 时间:2024/05/16 10:17
1 何为DOM?
www.w3.org官方的解释是:DOM 是HTML和XML文档的编程API。它定义了文档的逻辑结构和访问、操纵文档的方法。利用这组API,程序员可以对XML或HTML文档中的元素和内容进行任意的增删改查。这组API是与平台无关的,而且也是与编程语言无关的。这里的“对象模型”的含义取之于面向对象的编程思想。既然是对象就不仅包含属性,也包含操作属性的方法。所以DOM标准定义了这些属性和方法的名字及含义。
DOM包括DOM Core和DOM HTML两部分,DOM Core是用来操作XML的部分,也是操作HTML的基础。DOM HTML则是在DOM Core的基础上专门针对HTML增加了更多的对象、属性、方法。
2 DOM中节点(Node)的类型与继承
DOM把文档视为由Node构成的层级结构。构成文档的Node有很多类型,DOM Core 1中就定义了12中节点类型,不同节点类型具有不同的属性和方法。这12中节点类型如下:
- Document--文档节点,代表整个文档,可以有子节点,只能有一个元素类型的子节点。
- DocumentFragment
- DocumentType--不能有子节点
- EntityReference
- Element--元素节点,这也许是最重要的节点类型了吧
- Attr-属性节点
- ProcessingInstruction
- Comment
- Text--文本节点,不能有子节点
- CDATASection
- Entity
- Notation
DOM定义了上述每种节点类型的属性和方法,这里把Node这祖先类型和具体的Element类型、以及Attr类型的定义摘抄如下:
interface Node { // NodeType const unsigned short ELEMENT_NODE = 1; const unsigned short ATTRIBUTE_NODE = 2; const unsigned short TEXT_NODE = 3; const unsigned short CDATA_SECTION_NODE = 4; const unsigned short ENTITY_REFERENCE_NODE = 5; const unsigned short ENTITY_NODE = 6; const unsigned short PROCESSING_INSTRUCTION_NODE = 7; const unsigned short COMMENT_NODE = 8; const unsigned short DOCUMENT_NODE = 9; const unsigned short DOCUMENT_TYPE_NODE = 10; const unsigned short DOCUMENT_FRAGMENT_NODE = 11; const unsigned short NOTATION_NODE = 12; readonly attribute DOMString nodeName; attribute DOMString nodeValue; // raises(DOMException) on setting // raises(DOMException) on retrieval readonly attribute unsigned short nodeType; readonly attribute Node parentNode; readonly attribute NodeList childNodes; readonly attribute Node firstChild; readonly attribute Node lastChild; readonly attribute Node previousSibling; readonly attribute Node nextSibling; readonly attribute NamedNodeMap attributes; readonly attribute Document ownerDocument; Node insertBefore(in Node newChild, in Node refChild) raises(DOMException); Node replaceChild(in Node newChild, in Node oldChild) raises(DOMException); Node removeChild(in Node oldChild) raises(DOMException); Node appendChild(in Node newChild) raises(DOMException); boolean hasChildNodes(); Node cloneNode(in boolean deep);};
interface Element : Node { readonly attribute DOMString tagName; DOMString getAttribute(in DOMString name); void setAttribute(in DOMString name, in DOMString value) raises(DOMException); void removeAttribute(in DOMString name) raises(DOMException); Attr getAttributeNode(in DOMString name); Attr setAttributeNode(in Attr newAttr) raises(DOMException); Attr removeAttributeNode(in Attr oldAttr) raises(DOMException); NodeList getElementsByTagName(in DOMString name); void normalize();};
interface Attr : Node { readonly attribute DOMString name; readonly attribute boolean specified; attribute DOMString value;};
对于DOM HTML部分,则针对HTML对一些类进行了进一步的扩展,如对Element进行扩展,产生了HTMLElement类,如下:
interface HTMLElement : Element { attribute DOMString id; attribute DOMString title; attribute DOMString lang; attribute DOMString dir; attribute DOMString className;};HTML中的各种具体的元素节点也都从HTMLElement进行了进一步的扩展,如超链接标签<a >对应的HTMLAnchorElement:
interface HTMLAnchorElement : HTMLElement { attribute DOMString accessKey; attribute DOMString charset; attribute DOMString coords; attribute DOMString href; attribute DOMString hreflang; attribute DOMString name; attribute DOMString rel; attribute DOMString rev; attribute DOMString shape; attribute long tabIndex; attribute DOMString target; attribute DOMString type; void blur(); void focus();};
3 令人费解的文本节点---html文档中节点类型实例分析
为了弄清楚HTML文档中的节点关系,我们针对一段html代码进行分析。
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><div id="container">我是文本节点<p class="myclass">我也是文本类型的节点</p><br /></div><script>var div = document.getElementById('container');var childs = div.childNodes;for(i=0; i<childs.length; i++){document.write(i + "--节点类型:" + childs[i].nodeType + ", 节点名称:" + childs[i].nodeName + ", 节点值:" + childs[i].nodeValue + ", 节点值长度:" + (childs[i].nodeValue==null?"0":childs[i].nodeValue.length)+"<br/>");}</script></body></html>
这段js代码的输出结果如下:
1--节点类型:1, 节点名称:P, 节点值:null, 节点值长度:0
2--节点类型:3, 节点名称:#text, 节点值: , 节点值长度:3
3--节点类型:1, 节点名称:BR, 节点值:null, 节点值长度:0
4--节点类型:3, 节点名称:#text, 节点值: , 节点值长度:2
如果你能算出这段js代码的输出结果,那么说明对html文档结构与DOM的对应关系有比较细致的了解了,如果和你想的不一样,那么请继续看下面的分析:
首先是0号子节点:节点类型是文本节点,文本节点的节点值就是文本本身。对应“我是文本节点”这段文本,为什么长度是12而不是6呢?明明只有6个字啊。请注意这段文字前后的空格,其前面有2个Tab字符,下一行的前面也有两个Tab字符,这样就是6+2+2=10了,剩下的2个在哪里呢?那就是两个换行符。也就是说这个文本节点的内容其实是:\n\t\t我是文本节点\n\t\t,正好是12个字符。
再看1号节点,类型是元素节点,对应html中的<p></p>标签,元素标签的节点值都是null。
再看2号节点,是文本节点,基于0号节点的分析,我们知道这个文本的内容就是 \n\t\t,正好3个字符。
再看3号节点,是元素节点,对应<br/>标签,元素节点的节点值都是null。
再看4号节点,文本节点,对应 \n\t,正好2个字符。
由此可见,虽然html对于空白和换行直接忽略,但是使用DOM解析的时候,这些空白和换行会无故增加很多节点,增加浏览器端CPU和内存损耗。
4 DOM有时候会侵犯CSS地盘
css规定了html文档中元素如何呈现,注意这里是“元素”而不是节点。因为CSS选择器只能选择html中的元素节点,而不能选择其他类型的节点,如文本节点。那么为什么可以改变文本的显示呢?这是因为CSS是具有继承性的,文本节点必然是元素节点的子节点,所以它继承了元素节点的CSS特性。
由于选择器不能选择文本节点,所以处于同一元素节点下面的两个文本节点不能有各自独立的CSS特征值。如下:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style>body{color:red;}</style></head><body>我是第一段文本<br/>我是第二段文本</body></html>
这两个文本节点 ,都是body这个元素节点的子节点,我们无法通过css选择器分别为其指定显示特征。可见,元素节点是具有CSS特征的最小单位。
除此之外,css的选择器有时候不能满足用户需求,如一个表格的奇数行和偶数行采用不同的背景色,虽然可以通过为每一行增加class属性来通过css完成,但是一旦表格行数巨大,这将导致非常烦躁。此时使用DOM来动态设置反而更加简单。也许未来CSS的选择器能力将更加灵活强大,那样就没有必要让DOM来干这些”不正当“业务了。
5 属性节点的两种读写方式间的差别
直接上一个测试代码,看看属性节点到底什么意思。
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><div id="container" style="color:red;"></div><script>var div = document.getElementById('container');var childs = div.attributes;for(i=0; i<childs.length; i++){document.write(i + "--节点类型:" + childs[i].nodeType + ", 节点名称:" + childs[i].nodeName + ", 节点值:" + childs[i].nodeValue + ", 节点值长度:" + (childs[i].nodeValue==null?"0":childs[i].nodeValue.length)+"<br/>");}</script></body></html>
输出结果为:
0--节点类型:2, 节点名称:id, 节点值:container, 节点值长度:9
1--节点类型:2, 节点名称:style, 节点值:color:red;, 节点值长度:10
1--节点类型:2, 节点名称:style, 节点值:color:red;, 节点值长度:10
属性节点的类型代号为2,节点名称就是键名,节点的值为字符串。属性节点分为两种,一种是DOM Core和DOM HTML中规定的,如HTMLElement类规定了id,title等属性;另一种是程序员自定义的属性,键名可以是任意字符串。对于自定义的属性,只能通过getAttribute()来读取,通过setAttribute()来设置。而对于第一种属性来说,除了通过getAttribute()和setAttribute()来读写外,还可以直接使用点语法来读写,如下所示:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><input type="text" id="name" title="张三" /><script>var input = document.getElementById('name');input.title='李四';//input.setAttribute('title', '李四');var name1 = input.getAttribute('title');var name2 = input.title;document.write(name1 + "," + name2);</script></body></html>
上面两种方式,都可以改变input的title属性,效果完全相同。但是这并不是说对所有的属性都适合这条规则。同样的代码,我们把title属性替换成value属性。
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><input type="text" id="name" value="张三" /><script>var input = document.getElementById('name');//input.value='李四';input.setAttribute('value', '李四');var name1 = input.getAttribute('value');var name2 = input.value;document.write(name1 + "," + name2);</script></body></html>
运行结果表明,如果通过点语法改变value的值,则通过getAttribute('value')获得的值并没有因此改变;而如果通过setAttribute改变value的值,则通过点语法读取的value值会随之改变。可见此处的value属性有些特殊。
再看如下代码:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script>function f(){var input = document.getElementById('name');var name1 = input.getAttribute('value');var name2 = input.value;alert(name1 + "," + name2);}</script></head><body><input type="text" id="name" value="张三" /><input type="button" id="button" value="测试" onclick="f();" /></body></html>
页面显示后,我们在浏览器中手动修改输入框表单中的值为”李四“,如下所示:
可见,虽然我们修改了控件的值,但是通过getAttribute('value')读取到的属性值并没有改变,而通过input.value读取的值却实时反映了这种变化。其实这个例子中我们手动修改文本框的值和通过input.value="李四”的效果一样,都是没有改变名为value的属性值。
我们来看看HTMLInputElement的定义:
interface HTMLInputElement : HTMLElement { attribute DOMString defaultValue; attribute boolean defaultChecked; readonly attribute HTMLFormElement form; attribute DOMString accept; attribute DOMString accessKey; attribute DOMString align; attribute DOMString alt; attribute boolean checked; attribute boolean disabled; attribute long maxLength; attribute DOMString name; attribute boolean readOnly; attribute DOMString size; attribute DOMString src; attribute long tabIndex; readonly attribute DOMString type; attribute DOMString useMap; attribute DOMString value; //这就是那个特殊的value属性 void blur(); void focus(); void select(); void click();};
哪位高人能解释为什么这个名为value的属性会出现这种特殊的情况?????
与此相关的问题是,DOM也不能通过style属性读取元素来自外部css文件的配置信息。
另外,html标签中的属性名字和DOM定义属性名字也有不一致的时候,如HTML中的class属性,由于是js的保留字,所以不能直接使用,DOM将其对应到了className这个名字。
- 使用DOM操纵HTML文档几点粗浅认识
- 使用DOM操纵HTML文档几点粗浅认识
- 对于vc2005的几点粗浅认识
- 使用DOM技术操纵文档
- 使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- JavaScript高级应用:使用DOM技术操纵文档
- 使用DOM操作HTML文档
- HTML DOM(一):认识DOM
- 一.认识HTML DOM
- 使用dom对html文档进行解析
- html/css DOM脱离文档流的几种情况
- 对html,css,和JavaScript的粗浅认识
- 序员专用经典语录—看完笑一阵可以,千万不要死循环哦!
- 《软件性能测试过程详解与案例剖析》--读书笔记之性能测试过程模型PTGM
- mac下安装启动Mongodb
- 新人入驻csdn
- Stack & Heap
- 使用DOM操纵HTML文档几点粗浅认识
- 带你走进EJB--事务隔离级别
- CF369C(深搜巧用)
- ghjghjgh
- 关于鲁棒性的解释
- array 数组 一维数组 二维数组
- Starry Night
- 带你走进EJB--事务管理
- CodeForces 369C. Valera and Elections