从头认识js-DOM1
前面说过一个完整的js实现,包括ECMAScript,BOM,DOM三部分,现在就来讲讲DOM的有关知识。
DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序接口)。DOM描绘来一个层次化的节点树,允许开发人员添加,移除和修改页面的某一部分。
Node类型
DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现。每一个节点都会有一个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_REFERENCR_NODE(5)
6.Node.ENTITY_NODE(6)
7.Node.PROCESSING_INSTRUCTION_NODE(7)
8.Node.COMMENT_NODE(8)
9.Node.DOCUEMNT_NDOE(9)
10.Node.DOCUMENT_TYPE_NODE(10)
11.Node.DOCUMENT_FRAGMENT_NODE(11)
12.Node.NOTATION_NODE(12)
下面给出适用于所有浏览器中节点类型判断的方法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <ul id="ydb"> <li>item1</li> <li>item2</li> <li>item3</li> </ul> <script src="./create.js"></script> </body> </html>
var oUl = document.getElementById("ydb"); console.log(oUl); if (oUl.nodeType == 1) { console.log("该节点是元素节点"); var tagName = oUl.nodeName; var tagValue = oUl.nodeValue; console.log('nodeName:' + tagName); console.log('nodeValue:'+ tagValue); }
上面所示:我们实现了在所有浏览器中的节点类型的检测,因为IE中没有公开Node类型的构造函数,所以直接使用节点类型常量会出错,而且在节点为元素节点的时候,我们获取了元素节点的具体信息,有两个属性,一个是nodeName,另一个是nodeValue。nodeName始终都是保存着元素的标签名,而nodeValue的值始终为null。
下面介绍在DOM1中节点常用的属性和方法:
1.childNodes
每一个节点都一个一个childNodes属性,其中保存一个NodeList对象。NodeList是一种类数组,用于保存一组有序的节点,可以通过位置来访问这些节点。注意:NodeList是实时更新的,并不是某一个时刻的快照。
可以通过方括号,也可以使用item()方法访问保存在NodeList中的节点。
下面给出在所有浏览器中把类数组NodeList转化为数组的操纵:
function convertToArray(nodes) { var array = null; try { array = Array.prototype.slice(nodes, 0) } catch{ // IE8及更早版本将NodeList实现为一个COM对象,而导致不能像JScript对象那样使用这种对象 // 向后兼容 array = []; for (var i = 0, len = nodes.length; i < len; i++) { array.push(nodes[i]); } } return array; }
2.parentNode(每个节点都有一个parentNode属性,该属性指向文档树中的父节点)
3.previousSibling (指向该节点的上一个同胞节点,没有找到返回null)
4.nextSibling(指向该节点的下一个同胞节点,没有找到返回null)
5.firstChild (父节点的firstChild指向childNodes中的第一个节点)
6.lastChild (父节点的lastChild指向childNodes中的最后一个节点)
7.hasChildNodes() (该方法是一个非常有用的方法,在节点包含一个或多个子节点的情况下返回true,比查询childNodes列表的length属性更简单)
8.ownerDocument (该属性指向表示整个文档的文档节点。这种关系表示的是任何节点都属于它所在的文档,任何节点都不能同时存在于两个及其以上的文档中)
9.appendChild() (用于向使用该方法的节点中添加新的节点,如果新增的节点已经是文档的一部分了,那么就是将该节点从原来的位置转移到新位置,新增节点始终是放在末尾的,返回新增的节点)
10.insertBefore() (该方法接受两个参数:1.要插入的节点和作为参照的节点,新增的节点可以随意在任何位置,返回新增的节点)
11.replaceChild() (接受两个参数:1.要插入的节点 2.要替换的节点)
12.removeChild() (接受一个参数:1.要删除的节点,返回删除的节点)
上面所表述的属性和方法一般只适用于元素节点即nodeType为1的节点,下面介绍两个所有节点都适用的方法:
1.cloneNode() 用于创建调用该函数节点的一个副本,接受一个布尔值为参数,表示是否执行深复制。参数为true的时候,会复制节点及其整个子节点树,参数为false的时候,只复制节点本身。注意:复制的节点实际上是一个孤儿,没有存在当前文档中,除非用appendChild(),之类的方法,将其添加到文档中去。
cloneNode()不会复制添加到DOM节点中的JavaScript属性,例如事件处理程序等。但是在IE中它会复制事件处理程序,所以在复制之前最好先移除事件处理程序。
2.normalize() 处理文档树中的文本节点。由于解析器的实现或DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。当在某个节点上调用这个方法的时候,就在该节点的后在节点中查找上述两种情况。如果找到了空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点。
Document类型
JavaScript通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Docuemnt类型)的一个实例,表示整个HTML页面。而且,document对象是window对象的一个属性,因此可以作为全局对象来访问。该节点具有以下特征:
1.nodeType为9
2.nodeName为"#document"
3.nodeValue为null
4.parentNode为null
5.ownerDocument为null
6.其子节点可能是一个DocumentType(最多一个),Element(最多一个),ProcessingInstruction或Comment。
Document类型可以表示HTML页面或者其他XML文档。不过,最常见的应用还是作为HTMLDocument实例的document对象。通过这个文档对象,不仅可以取得与页面有关的信息,而且还能操作页面的外观及其底层结构。
1.文档的子节点
1.document.docuemntElement 取得对html的引用
2.docuemnt.body 取得对body的引用
3.docuemnt.doctype 取得对<!DOCTYPE>的引用
多数情况下,我们用不着在document对象上调用appendChild(),removeChild()和replaceChild()方法,因为文档类型(如果存在的话)是只读的,而且它只有一个元素子节点(该节点通常早就存在了)。
2.文档信息
1.document.title 取得文档标题可以进行修改。
2.doument.URL 取得完整的URL。
3.document.domain 取得域名
4.document.referrer 取得来源页面的URL
2,3,4所表示的信息都存在于请求的HTTP头部,只不过是通过这些属性让我们能够在JavaScript中访问它们而已。
只有domain是可以设置的,由于跨域安全限制,来自不同子域页面无法通过JavaScript通信。而将每个页面的document.domain设置为相同的值,这些页面就可以互相方法对方包含的JavaScript的对象了。
3.查找元素
说到最常见的DOM应用,恐怕就要数取得特定的某个元素或者某组元素的引用,然后再执行一些操作。
1.getElementById() 接受一个参数:要取得元素的ID。如果找到相应的元素则返回该元素,如果不存在带有相应ID的元素,则返回null。注意,这里的ID必须与页面中元素的id特性严格匹配,包括大小写。
2.getElementsByTagName() 接受一个参数,即要取得元素的标签名,而返回的是包含领个或多个元素的NodeList。
3.getElementsByName() 接受一个参数,元素name特性的名称,这个方法返回带有给定name特性的所有元素。
4.特殊集合
除了属性和方法,document对象还有一些特殊的集合。这些集合都是HTMLCollection对象,为访问文档常用的部分提供了快捷方式,包括:
1.document.anchors 包含文档中所有带name特性的a元素。
2.document.applets 包含文档所有的applet元素,因为不再推荐使用applet元素,所以这个集合不建议在使用了。
3.document.forms 包含文档中所有的form元素。
4.document.images 包含文档中的img元素。
5.document.links 包含文档中所有带href特性的a元素。
5.文档写入
有一个document对象的功能已经存在多年了,那就是将输入流写入到网页中的能力。
1.document.write() 会原样写入。
2.document.writeln() 会在字符串的末尾添加一个换行符。
3.document.open()
4.docuemnt.close()
方法open()和close() 分别用于打开和关闭网页额输出流。如果是在页面加载期间使用write()或writeln()方法,则用不到这两个方法。
Element类型
除了Document类型之外,Element类型就要算是Web编程中最常用额类型了。Element类型用于表现XML或HTML元素,提供了对元素标签名,子节点以及特性的访问。Element节点具有以下特征:
1.nodeType为1
2.nodeName为元素的标签名
3.nodeValue为null
4.parentNode可能是Document或Element
5.其子节点可能是Element,Text,Comment,ProcessingInstruction,CDATASection或EntityReference
6.tagName为元素的标签名
1.HTML元素
所有HTML元素都由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示。HTMLLElement类型直接继承自Element并添加了一些属性。添加的这些属性分别对应于每个HTML元素中都存在的下列标准特性。
1.id 元素在文档中的唯一标识符
2.title 有关元素的附加说明信息,一般通过提示条显示出来
3.lang 元素内容的语言代码,很少使用
4.dir 语言的方向,值为“ltr”或“rtl”
5.className 与元素的class特性对应,即为元素指定的CSS类。
2.特性操作
操作特性的DOM方法主要有三个:
1.getAttribute()
2.setAttribute()
3.removeAttribute()
这三个方法可以针对任何特性使用,包括那些以HTMLElement类型属性的形式定义的特性。
有两类的特性,它们虽然有对应的属性名,但属性的值与通过getAttribute()返回的值并不相同。
第一类特性就是style,用于通过CSS为元素指定样式。在通过getAttribute()访问时,返回的style特性值中包含的是CSS文本,而通过属性来访问它则会返回一个对象。由于style属性是用于以编程方式访问元素样式的,因此并没有映射到style属性。
第二类与众不同的特性是onclick这样的事件处理程序。当在元素上使用时,onclick特性中包含的是JavaScript代码,如果通过getAttribute()访问,则会返回相应代码的字符串。而在访问onclick属性时,则会返回一个JavaScript函数(如果未在元素中指定相应特性,则返回null)。这是因为onclick及其其他事件处理程序属性本身就应该被赋予函数值。
由于存在这些差别,再通过JavaScript以编程方式操作DOM时,开发人员,经常不使用getAttribute(),而是只使用对象的属性。只有在取得自定义特性值的情况下,才会使用getAttribute()方法。
3.attributes属性
Element类型是使用attributes属性的唯一一个DOM节点类型。attributes属性中包含一个NamedNodeMap,与NodeList类似,也是一个动态集合。元素的每一个特性都由一个Attr节点 标示,每个节点都保存在NamedNodeMap对象中。NamedNodeMap对象拥有下列方法。
1.getNamedItem(name) 返回nodeName属性等于name的节点;
2.removeNamedItem(name) 从列表中删除nodeName属性等于name的节点;
3.setNamedItem(node) 向列表中添加节点,以节点的nodeName属性为索引。
4.item(pos) 返回位于数字pos位置处的节点
注意:每个特性节点都有一个名为specified的属性,这个属性如果为true,则意味着要么是在HTML中指定相应特性,要么是通过setAttribute()方法设置了特性。
4.创建元素
1.document.createElement() 接受一个参数,即要创建元素的标签名。返回一个DOM元素的引用。
Text类型
文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容。纯文本内容可以包含转义后的HTML字符,但不能包含HTML代码。Text节点具有以下特征:
1.nodeType为3
2.nodeName为“#text”
3.nodeValue的值为节点所包含的文本
4.parentNode是一个Element
5.没有子节点
6.可以通过nodeValue属性或data属性访问text节点中所包含的文本,这两个属性中包含的值相同。对nodeValue的修改也会通过data反映出来,反之亦然。
7.appendData(text) 将text添加到节点的末尾
8.deleteData(offset,count) 从offset指定的位置开始删除count个字符
9.insertData(offset,text) 在offset指定的位置插入text
10.replaceData(offset,count,text) 用text替换从offset指定的位置开始到offset+count为为止处的文本
11.splitText(offset) 从offset指定的位置将当前文本节点分成两个文本节点
12.substringData(offset,count) 提取从offset指定的位置开始到offset+count为止的字符串。
13.length属性,保存着节点中字符的数目。
1.创建文本节点
document.createTextNode() 创建新文本节点,接受一个参数:要插入节点中的文本。
Comment类型
注释是在DOM中通过Comment类型来表示的。Comment节点具有以下特征:
1.nodeType为8
2.nodeName为“#comment”
3.nodeValue为注释的内容
4.parentNode为Document或Element