DOM(文档对象模型)
@针对HTML和XML文档的一个API,为基本的文档结构及查询提供接口。
@IE中的DOM都是以COM对象的形式实现的,故IE中的DOM对象于原生JavaScript对象的行为或活动特点有差异。
10.1节点层次
@DOM能够将任何HTML或XML文档庙会成一个由多层节点构成的结构。
@每个文档只能有一个文档元素,在HTML页面中,文档元素为<html>元素。【根节点为Document,最外层元素为文档元素html】
@HTML元素通过元素节点表示,特性(attribute)通过特性节点表示,文档类型通过文档类型节点表示,注释通过注释节点表示。
10.1.1 Node类型
@DOM1级定义了Node接口,由DOM中的所有节点类型实现。除了IE外,JavaScript中的节点都是继承自Node类型。
@节点类型由Node类型定义的12个数值常量表示:
Node.ELEMENT_NODE(1);
Node.ELEMENT_NODE (1)
Node.ATTRIBUTE_NODE (2)
Node.TEXT_NODE (3)
Node.CDATA_SECTION_NODE (4)
Node.ENTITY_REFERENCE_NODE(5)
Node.ENTITY_NODE (6)
Node.PROCESSING_INSTRUCTION_NODE (7)
Node.COMMENT_NODE (8)
Node.DOCUMENT_NODE (9)
Node.DOCUMENT_TYPE_NODE (10)
Node.DOCUMENT_FRAGMENT_NODE (11)
Node.NOTATION_NODE (12)
@通过上面的常量能判断节点的类型,但由于IE没有公开Node类型的构造函数,故应该用数字值进行比较:
if (someNode.nodeType == Node.ELEMENT_NODE){ //在IE中无效 alert("元素节点"); } if (someNode.nodeType == 1){ //所有浏览器适应 alert("元素节点"); }
① nodeName 和 nodeValue
@对于元素节点,nodeName保存元素的标签名,nodeValue值为null。
② 节点关系
每个节点都有一个childNodes属性,保存着一个NodeList对象(一种类数组对象,保存一组有序的节点)。
@可通过方括号语法和item()方法访问NodeList的值,有length属性,但不是Array的实例,而是基于DOM结构动态查询的结果。
@在IE8-浏览器中,会为空白符创建节点,length属性值会包含空白符节点。
var firstChild = someNode.childNodes[0]; var secondChild = someNode.childNodes.item(1); var count = someNode.childNodes.length;
@length属性表示的是访问NodeList那一刻节点的数量。
@将NodeList对象转换为数组:使用Array.prototype.slice()【IE8及以下无效,需要手动枚举所有成员】
function toArray(){ var array = null; try { array = Array.prototype.slice.call(nodes, 0); //针对IE9+等浏览器 } catch(ex){ array = new Array(); for (var i = 0; i < nodes.length; i++) { //针对IE8- array.push(nodes[i]); }; } return array; }
每个节点都有一个parentNode属性。包含在NodeList列表中的所有节点具有相同的父节点,他们的parentNode指向同个父节点。
每个节点通过previousSibling和nextSibling属性访问相邻节点。首个节点的previousSibling和末尾节点的nextSibling都是null。
@只有一个子节点时,firstChild和lastChild指向同个子节点。没有节点时都为null。
@hasChildNodes()方法在节点包含子节点时返回true。
③ 操作节点
appendChild():1个子节点参数。向NodeList列表末尾添加一个新节点。
@当传入的节点已经是文档的一部分时,该节点讲过从原点的位置转移到新位置。
insertBefore():2个参数。在指定节点前插入一个新节点。
@当指定的节点即第一个参数为null时,insertBefore()和appendChild()执行相同的操作。
//插入后成为最后一个子节点 returnedNode = someNode.insertBefore(newNode,null); alert(newNode == someNode.lastChild); //true //插入后成为第一个子节点 returnedNode = someNode.insertBefore(newNode,firstChild); alert(returnedNode == newNode ); //true alert(newNode == someNode.firstChild); //true //插入到最后一个子节点前面 returnedNode = someNode.insertBefore(newNode,someNode.lastChild); alert(newNode == someNode.childNodes[someNode.childNodes.lehgth-2]); //true
replaceChild():2个参数。以上述2种不同的是,这个方法会代替原来的节点。
@插入一个节点时,原节点的所有关系指针都会被代替节点复制过去,但原节点仍在文档中,只是没有了自己的位置。
//替换第一个子节点 var returnedNode = someNode.replaceChild(newNode,someNode.firstChild); //替换最后一个子节点 returnedNode = someNode.replaceChild(newNode,someNode.lastChild);
removeChild():1个参数。移除节点。移除的节点成为方法的返回值。
@同样,移除的节点仍为文档所有,只是没有了自己的位置。
前面4中操作方法,都需要先取得父节点。使用该4种方法操作不支持子节点的节点时,会导致错误发生。
④ 其他方法
2个所有类型节点都有的方法:cloneNode() 和 normalize()
cloneNode():1个布尔值参数(表是否执行深复制)。用于创建调用这个方法的节点的一个完全相同的副本。
参数为true时,执行深复制,即复制节点及其整个子节点树。
参数为false时,执行浅复制,即只复制节点本身。
@cloneNode():不会复制DOM节点的JavaScript属性(如事件处理程序),只复制特性。IE则会复制JavaScript属性。
normalize():用于处理文档树中的文本节点:删除空文本节点 和 合并相邻文本节点。
10.1.2 Document 类型
@JavaScript通过Document类型表示文档(HTML或XML)。浏览器中,document是HTMLDocument(继承自Document类型)的一个实例。
@document对象表示整个HTML页面,是window对象的属性,故可作为全局对象来访问。
nodeType=9
nodeName="#document"
nodeValue、parentNode、ownerDocument = null
子节点 可能是:DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction 或 Comment。
① 文档的子节点
@访问document子节点的2个快捷方式:documentElement属性 和 通过childNodes列表访问文档元素。
var html = document.documentElement; //取得对<html>的引用 //html的值 与 document.childNodes[0] 和 document.firstChild相同。
@document对象还有一个body属性,指向<body>元素。
@Document有一个可能的子节点DocumentType。
通常将<!DOCTYPE>标签看成一个与文档其他部分不同的实体,可通过doctype属性访问,但该属性兼容性差。
② 文档信息
@作为HTMLDocument的实例,document对象有一些标准Document对象没有的属性。
@title属性:将<title>元素中的文本,显示在浏览器窗口的标题栏的标签页上。
@存在请求的HTTP头部的属性:
URL属性,包含网页完整的URL。 var url = document.URL;
domain属性,包含页面的域名。
referrer属性,保存着链接到当前页面的那个页面的URL。没有来源页面时,为空字符串。
@3个中只有domain可设置,但受安全限制:
如:URL为aa.bbb.com时,domain只能设为bbb.com;
URL为www.bbb.com时,domain只能设为bbb.com。
不能将domain设置为URL不包含的域。
@跨域:当包含来自其他子域的框架或内嵌框架时,由于安全限制,默认不能与不同子域的页面进行JavaScript通信。
但通过将彼此的document.domain设置相同值,就能互访对方的JavaScript对象。
如:主页www.bbb.com,框架内的页面aa.bbb.com,设置彼此的document.domain = "bbb.com";,就能互访。
@对domain的另一个限制:不能将"松散的"(loose)domain属性 再设置为"紧绷的"(tight)
如:不能将松散的"bbb.com"设置为紧绷的"aa.bbb.com"。
③ 查找元素
Document类型提供2种方法:getElementById() 和 getElementByTagName()
getElementById():通过元素的ID引用元素。
@当页面有多个元素相同ID时,返回文档中第一次出现的元素。
@在IE7及以下版本中,name值以ID相同的表单元素也会被返回。当name与ID值相同的表单元素位于前面时,后面的“ID元素”不会被返回。
应该避免表单元素中name属性与其他元素的ID值相同。
getElementByTagName():接收标签名,返回包含零或多个元素的NodeList。在HTML中,返回一个HTMLCollection对象,一个"动态"集合。
@通过方括号语法 、item()方法 和 name值 访问HTMLCollection对象中的项,元素数量通过其length属性取得。
@HTMLCollection对象的namedItem()方法可通过元素name特性取得集合中的项。
@对HTMLCollection而言,可向方括号中传入数值或字符串形式的牵引值,
在后台,对数值牵引就会调用item()方法,对于字符串就会调用namedItem()。
getElementByName():返回给定name特性的所有元素。常用于取得单选按钮。
④ 特殊集合
document.anchors:包含所有带name特性的<a>元素。
document.links:包含所有带href特性的<a>元素。
document.forms:包含所有<form>元素。结果同document.getElementByTagName(“form”);
document.images:包含所有<img>元素。
⑤ 文档写入
将输出流写入页面的4个方法:write()、writeln()、opne() 和 close()
@write()原样写入。writeln()在字符串较为添加一个换行符(\n)。
@输入"</script>"时,应该添加转义序列,不然会被解释为与外部<script>标签匹配,' "); '会出现在页面中。
document.write("<script type=\"text\javascript\" src=\"file.js\">" + "<\/script>");
@加载结束后,再调用document.write()输出的内容会重写整个页面。
<body>
<p>This is some content that you won't get to see because it will be overwritten.</p>
<script type="text/javascript">
window.onload = function(){
document.write("Hello world!");
};
</script>
</body>