第10章 DOM
1. 节点层次
文档节点
是每个文档的根节点。
(1) Node 类型
- 每个节点都有一个
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_FRAGMENT_NODE(11);
(12) Node.NOTATION_NODE(12)。
- IE 没有公开 Node 类型的构造函数,为了确保跨浏览器兼容,最好还是将
nodeType 属性与数字值
进行比较。
* nodeName
和 nodeValue
属性
* 节点关系
- 每个节点都有一个
childNodes
属性,其中保存着一个 NodeList 对象。
- 每个节点都有一个
- NodeList 是一种类数组 对象,用于保存一组有序的节点,可以通过位置来访问这些节点。
- 虽然可以通过方括号语法来 访问 NodeList 的值,而且这个对象也有
length 属性
,但它并不是 Array 的实例
。- NodeList 对象的独特之处在于,它实际上是
基于 DOM 结构动态执行查询的结果
,因此 DOM 结构的变化能够自动反映在 NodeList 对象中。
- 访问保存在 NodeList 中的节点——可以通过方括号,也可以使用 item() 方法。
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
- 将 NodeList 对象转换为数组
function convertToArray(nodes){
var array = null;
try {
array = Array.prototype.slice.call(nodes, 0); //针对非 IE 浏览器
} catch (ex) {
array = new Array();
for (var i=0, len=nodes.length; i < len; i++){
array.push(nodes[i]);
}
}
return array;
}
- 每个节点都有一个
parentNode
属性,该属性指向文档树中的父节点。
- 每个节点都有一个
包含在 childNodes 列表中 的所有节点都具有相同的父节点,因此它们的 parentNode 属性都指向同一个节点。
- 包含在 childNodes 列表中的每个节点相互之间都是同胞节点。通过使用列表中每个节点的
previousSibling
和nextSibling
属性,可以访问同一列表中的其他节点。
- 包含在 childNodes 列表中的每个节点相互之间都是同胞节点。通过使用列表中每个节点的
- 父节点的
firstChild
和lastChild
属性分别指向其 childNodes 列表中的第一个和最后一个节点。
节点关系
- 父节点的
-
5.
hasChildNodes()方法
在节点包含一或多个子节点的情况下返回 true。 -
ownerDocument属性
指向表示整个文档的文档节点。
-
* 操作节点
-
appendChild()
方法:用于向 childNodes 列表的末尾添加一个节点。
如果传入到 appendChild()中的节点已经是文档的一部分了,那结果就是将该节点从原来的位置转移到新位置。
//someNode 有多个子节点
var returnedNode = someNode.appendChild(someNode.firstChild);
alert(returnedNode == someNode.firstChild); //false
alert(returnedNode == someNode.lastChild); //true
-
insertBefore()
方法:接受两个参数:要插入的节点
和作为参照的节点
。插入节点后,被插 入的节点会变成参照节点的前一个同胞节点(previousSibling),同时被方法返回。
如果参照节点是 null,则 insertBefore()与 appendChild()执行相同的操作
。
3.replaceChild()
方法:接受的两个参数是:要插入的节点
和要替换的节点
。要替换的节点将由这个 方法返回并从文档树中被移除,同时由要插入的节点占据其位置。
4.removeChild()
方法:接受一个参数,即要移除 的节点。被移除的节点将成为方法的返回值。
* 其他方法
-
cloneNode()
方法:用于创建调用这个方法的节点的一个完全相同的副本。接受一个布尔值参数,表示是否执行深复制。在参数为 true 的情况下,执行深复制,也就是复制节点及其整个子节点树;在参数为 false 的情况下,执行浅复制, 即只复制节点本身。
2.normalize()
方法:由于解析器的实现或 DOM 操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点 的情况。当在某个节点上调用这个方法时,就会在该节点的后代节点中查找上述两种情况。如果找到了空文本节点,则删除它;如果找到相邻的文本节点,则将它们合并为一个文本节点。
(2) Document类型
- JavaScript 通过 Document 类型表示文档。
- 在浏览器中,document 对象是 HTMLDocument(继承自 Document 类型)的一个实例,表示整个 HTML 页面。
- document 对象是 window 对象的一个 属性,因此可以将其作为全局对象来访问。
Document 节点具有下列特征:
(1) nodeType 的值为 9;
(2) nodeName 的值为"#document";
(3) nodeValue 的值为 null;
(4) parentNode 的值为 null;
(5) ownerDocument 的值为 null;
(6) 其子节点可能是一个 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction
或 Comment。
* 文档的子节点
Document 节点的子节点可以是DocumentType、Element、ProcessingInstruction 或 Comment。
1.两个内置的访问其子节点的快捷方式
:
documentElement 属性
,该属性始终指向 HTML 页面中的<html>元素。- 通过 childNodes 列表访问文档元素。
-
document.body
,body 属性,直接指向<body>元素。
3.Document 另一个可能的子节点是 DocumentType。通常将<!DOCTYPE>标签看成一个与文档其他 部分不同的实体,可以通过 doctype 属性(在浏览器中是 document.doctype
)来访问它的信息。
* 文档信息
-
title属性
:可以取得当前页面的标题,也可以修改当前页面的标题并反映在浏览器的标题栏中。(document.title
) -
URL属性
:包含页面完整的 URL(即地址栏中显示的 URL)。(document.URL
) -
domain 属性
:只包含页面的域名。(document.domain) -
referrer 属性
: 保存着链接到当前页面的那个页面的 URL。在没有来源页面的情况下,referrer 属性中可能 会包含空字符串。(document.referrer)
(1) 只有
domain 是可以设置
的。但由于安全方面的限制,也并非可以给 domain 设 置任何值。如果 URL 中包含一个子域名,例如 p2p.wrox.com,那么就只能将 domain 设置为"wrox.com" (URL 中包含"www",如 www.wrox.com 时,也是如此)。不能将这个属性设置为 URL 中不包含的域。
//假设页面来自 p2p.wrox.com 域
document.domain = "wrox.com"; // 成功
document.domain = "nczonline.net"; // 出错!
(2) 浏览器对 domain 属性还有一个限制,即如果域名一开始是“松散的”(loose),那么不能将它再设 置为“紧绷的”(tight)。换句话说,在将 document.domain 设置为"wrox.com"之后,就不能再将其 设置回"p2p.wrox.com",否则将会导致错误。
//假设页面来自于 p2p.wrox.com 域
document.domain = "wrox.com"; //松散的(成功)
document.domain = "p2p.wrox.com"; //紧绷的(出错!)
*查找元素
getElementById()
(1) 接收一个参数:要取得的元素的 ID。如果找到相应的元素则返回该元素,如果不存在带有相应 ID 的元素,则返回 null。
(2) 如果页面中多个元素的 ID 值相同,getElementById()只返回文档中第一次出现的元素
。
(3) ID 必须与页面中元素的 id 特性(attribute)严格匹配
,包括大小写
-
getElementsByTagName()
:
(1) 接受一个参数,即要取得元素的标签名,而返回的是包含零或多个元素的 NodeList。
(2) 在 HTML 文档中,这个方法会返回一 个HTMLCollection 对象
,作为一个“动态”集合,该对象与 NodeList 非常类似。
(3) 与 NodeList 对象类似,可以 使用方括号
语法或item()方法
来访问 HTMLCollection 对象中的项。而这个对象中元素的数量则可以 通过其length 属性
取得。
var images = document.getElementsByTagName("img");
alert(images.length);//输出图像的数量
alert(images[0].src); //输出第一个图像元素的 src 特性
alert(images.item(0).src);//输出第一个图像元素的 src 特性
(4) HTMLCollection 对象还有一个方法,叫做
namedItem()
,使用这个方法可以通过元素的 name 特性取得集合中的项。
<img src="myimage.gif" name="myImage">
var myImage = images.namedItem("myImage");
(5) HTMLCollection 还支持按名称访问项,对命名的项也可以使用方括号语法来访问。
var myImage = images["myImage"];
对 HTMLCollection 而言,我们可以向方括号中传入数值或字符串形式的索引值。在后台,对数 值索引就会调用 item(),而对字符串索引就会调用 namedItem()。
(6) 要想取得文档中的所有元素,可以向 getElementsByTagName()中传入"*"。
3.getElementsByName()
:
(1) 只有 HTMLDocument 类型才有的方法,这个方法会返回带有给定 name 特性的所有元素。
* 特殊集合
(1)
document.anchors
,包含文档中所有带 name 特性的<a>元素;
(2)document.applets
,包含文档中所有的<applet>元素,因为不再推荐使用<applet>元素,所以这个集合已经不建议使用了;
(3)document.forms
,包含文档中所有的<form>元素,与 document.getElementsByTagName("form")得到的结果相同;
(4)document.images
,包含文档中所有的<img>元素,与 document.getElementsByTagName("img")得到的结果相同;
(5)document.links
,包含文档中所有带 href 特性的<a>元素。
* DOM 一致性检测
由于 DOM 分为多个级别,也包含多个部分,因此检测浏览器实现了 DOM 的哪些部分就十分必要 了。document.implementation 属性
就是为此提供相应信息和功能的对象,与浏览器对 DOM 的实现直接对应。
(1) DOM1 级只为 document.implementation 规定了一个方法,即
hasFeature()
。这个方 法接受两个参数:要检测的 DOM 功能的名称及版本号。如果浏览器支持给定名称和版本的功能,则该方法返回 true。
var hasXmlDom = document.implementation.hasFeature("XML", "1.0");
DOM 功能
* 文档写入
write()
和writeln()
方法都接受一个字符串参数,即要写入到输出流中的文本。write()会原样写入,而 writeln()则会 在字符串的末尾添加一个换行符(\n)。
(1) 在页面被加载的过程中,可以使用这两个方法向页面中动态地加入内容。
<html>
<head>
<title>document.write() Example</title>
</head>
<body>
<p>The current date and time is:
<script type="text/javascript">
document.write("<strong>" + (new Date()).toString() +
"</strong>"); </script>
</p>
</body>
</html>
不能直接包含字符串"</script>",因为这会导致该 字符串被解释为脚本块的结束,它后面的代码将无法执行。需加入转义字符\即可
(2) 如果在文档加载结束后再调用 document.write(),那么输出的内容将会重写整个页面。
<html>
<head>
<title>document.write() Example 4</title>
</head>
<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>
</html>
方法
open()
和close()
分别用于打开和关闭网页的输出流。如果是在页面加载期间使用 write()或 writeln()方法,则不需要用到这两个方法。
(3) Element类型
Element 类型用于表现XML或HTML 元素,提供了对元素标签名、子节点及特性的访问。
Element 节点具有以下特征:
(1) nodeType 的值为 1;
(2) nodeName 的值为元素的标签名;
(3) nodeValue 的值为 null;
(4) parentNode 可能是 Document 或 Element;
(5) 其子节点可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或EntityReference。
- 要访问元素的标签名,可以使用
nodeName
属性,也可以使用tagName
属性; - 在 HTML 中,标签名始终都以全部大写表示,div.tagName 实际上输出的是 "DIV"而非"div"。
*HTML元素
- 所有 HTML 元素都由
HTMLElement
类型表示,不是直接通过这个类型,也是通过它的子类型来表示。 - HTMLElement 类型直接继承自 Element 并添加了一些属性。添加的这些属性分别对应于每个 HTML 元素中都存在的下列标准特性。
(1) id,元素在文档中的唯一标识符。
(2) title,有关元素的附加说明信息,一般通过工具提示条显示出来。
(3) lang,元素内容的语言代码,很少使用。
(4) dir,语言的方向,值为"ltr"(left-to-right,从左至右)或"rtl"(right-to-left,从右至左),
也很少使用。
(5) className,与元素的 class 特性对应,即为元素指定的 CSS 类。
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr">
</div>
var div = document.getElementById("myDiv");
alert(div.id);//"myDiv""
alert(div.className);//"bd"
alert(div.title);//"Body text"
alert(div.lang);//"en"
alert(div.dir);//"ltr"
* 取得特性
getAttribute()
方法:
- 通过 getAttribute()方法也可以
取得自定义特性
(即标准 HTML 语言中没有的特性)的值。
2.特性的名称是不区分大小写
的,即"ID"和"id"代表的都是同一个特性。
任何元素的所有特性,也都可以通过 DOM 元素本身的属性来访问。只有公认的(非自定义的)特性才会以属性的形式添加到 DOM 对象中。
两类特殊的特性属性的值与通过 getAttribute()返回的值不相同:
(1) 第一类特性就是
style
,用于通过 CSS 为元素指定样式。在通过 getAttribute()访问时,返 回的 style 特性值中包含的是 CSS 文本,而通过属性来访问它则会返回一个对象。
(2) 第二类特性是onclick 这样的事件处理程序
。当在元素上使用时,onclick 特性中包 含的是 JavaScript 代码,如果通过 getAttribute()访问,则会返回相应代码的字符串。而在访问 onclick 属性时,则会返回一个 JavaScript 函数(如果未在元素中指定相应特性,则返回 null)。
* 设置特性
setAttribute()
方法:
- 这个方法
接受两个参数
:要设置的特性名和值。如果特性已经存在,setAttribute()会以指定的值替换现有的值;如果特性不存在,setAttribute() 则创建该属性并设置相应的值。 - 通过这个方法设置的 特性名会被统一转换为
小写形式
,即"ID"最终会变成"id"。
(1) 因为所有特性都是属性,所以直接给属性赋值可以设置特性的值。
(2) 为 DOM 元素添加一个自定义的属性,该属性不会自动成为元素的特性。
removeAttribute()
方法:
这个方法用于彻底删除元素的特性
。调用这个方法不仅会清除特性的值,而且也会从元素中完全删除特性。
*attributes 属性
1.Element 类型是使用 attributes 属性的唯一一个 DOM 节点类型。
2.attributes 属性中包含一个NamedNodeMap,与 NodeList 类似,也是一个“动态”的集合。元素的每一个特性都由一个 Attr 节 点表示,每个节点都保存在 NamedNodeMap 对象中。
NamedNodeMap
对象拥有下列方法:
(1) getNamedItem(name):返回 nodeName 属性等于 name 的节点;
(2) removeNamedItem(name):从列表中移除 nodeName 属性等于 name 的节点;
(3) setNamedItem(node):向列表中添加节点,以节点的 nodeName 属性为索引;
(4) item(pos):返回位于数字 pos 位置处的节点。
- attributes 属性中包含一系列节点,每个节点的
nodeName 就是特性的名称
,而节点的nodeValue 就是特性的值
。
var id = element.attributes.getNamedItem("id").nodeValue;
//简写方式
var id = element.attributes["id"].nodeValue;
//设置新值
element.attributes["id"].nodeValue = "someOtherId";
-
调用
removeNamedItem()方法
与在元素上调用 removeAttribute()方法的效果相同——直接删 除具有给定名称的特性。两个方法间唯一的区别
,即 removeNamedItem()返回表示 被删除特性的 Attr 节点。 -
针对 attributes 对象中的特性,不同浏览器返回的
顺序不同
。这些特性在 XML 或 HTML 代 码中出现的先后顺序,不一定与它们出现在 attributes 对象中的顺序一致。 -
IE7 及更早的版本会
返回 HTML 元素中所有可能的特性
,包括没有指定的特性。换句话说,返回 100 多个特性的情况会很常见。
每个特 性节点都有一个名为
specified 的属性
,这个属性的值如果为 true,则意味着要么是在 HTML 中指定了相应特性,要么是通过 setAttribute()方法设置了该特性。在 IE 中,所有未设置过的特性的该 属性值都为 false,而在其他浏览器中根本不会为这类特性生成对应的特性节点(因此,在这些浏览器 中,任何特性节点的 specified 值始终为 true)。
function outputAttributes(element){
var pairs = new Array(),
attrName,
attrValue,
i,
len;
for (i=0, len=element.attributes.length; i < len; i++){
attrName = element.attributes[i].nodeName;
attrValue = element.attributes[i].nodeValue;
if (element.attributes[i].specified) {
pairs.push(attrName + "=\"" + attrValue + "\"");
}
}
return pairs.join(" ");
}
* 创建元素
document.createElement()
方法可以创建新元素。
-
这个方法只
接受一个参数
,即要创建元素的标签名。 -
这个标签名在
HTML 文档中不区分大小写
,而在 XML(包括 XHTML)文档中,则是区 分大小写的。 -
在
IE 中
可以以另一种方式使用 createElement(),即为这个方法传入完整的元素标签,也可以包含属性。
var div = document.createElement("<div id=\"myNewDiv\"
class=\"box\"></div >");
*元素的子节点
-
元素的 childNodes 属性中包含了它的所有子节点,这些子节点有可能是元素、文本节点、注释或处理指令。
-
不同浏览器在看待这些节点方面存在显著的不同,返回的子节点不相同。
-
如果需要通过 childNodes 属性遍历子节点,要先检查 一下 nodeTpye 属性。
for (var i=0, len=element.childNodes.length; i < len; i++){
if (element.childNodes[i].nodeType == 1){ 12
//执行某些操作 }
}
- 元素也支持
getElementsByTagName()
方法。在通过元素调用这个方法时,除了搜索起点是当前元素之外,其他 方面都跟通过 document 调用这个方法相同,因此结果只会返回当前元素的后代。
var ul = document.getElementById("myList");
var items = ul.getElementsByTagName("li");
(4) Text 类型
-
文本节点
由 Text 类型表示,包含的是可以照字面解释的纯文本内容。 - 纯文本中可以包含
转义后的 HTML 字符
,但不能包含 HTML 代码。
Text 节点具有以下特征
:
(1) nodeType 的值为 3;
(2) nodeName 的值为"#text";
(3) nodeValue 的值为节点所包含的文本; parentNode 是一个 Element;
(4) 不支持(没有)子节点。
- 通过
nodeValue 属性
或data 属性
访问 Text 节点中包含的文本,这两个属性中包含的值相同。对 nodeValue 的修改也会通过 data 反映出来,反之亦然。
操作节点中文本的方法
:
(1) appendData(text):将 text 添加到节点的末尾。
(2) deleteData(offset, count):从 offset 指定的位置开始删除 count 个字符。
(3) insertData(offset, text):在 offset 指定的位置插入 text。
(4) replaceData(offset, count, text):用 text 替换从 offset 指定的位置开始到 offset+count 为止处的文本。
(5) splitText(offset):从 offset 指定的位置将当前文本节点分成两个文本节点。
(6) substringData(offset, count):提取从 offset 指定的位置开始到 offset+count 为止
处的字符串。
-
文本节点还有一个
length 属性
,保存着节点中字符的数目。而且,nodeValue.length 和 data.length 中也保存着同样的值。 -
在默认情况下,每个可以包含内容的元素
最多只能有一个文本节点
,而且必须确实有内容存在。
访问文本子节点:
var textNode = div.firstChild; //或者div.childNodes[0]
//取得了文本节点的引用后修改它。
div.firstChild.nodeValue = "Some other message";
- 在修改文本节点时还要注意,此时的字
符串会经过 HTML
(或 XML,取决于文档类型)编码。换句话说, 小于号、大于号或引号都会像下面的例子一样被转义。
//输出结果是"Some <strong>other</strong> message"
div.firstChild.nodeValue = "Some <strong>other</strong> message";
* 创建文本节点
document.createTextNode()
创建新文本节点。
- 这个方法接受一个参数——要插入节点 中的文本。
- 与设置已有文本节点的值一样,作为参数的文本也将按照 HTML 或 XML 的格式进行编码。
- 一般情况下,每个元素只有一个文本子节点。不过,在某些情况下也可能包含
多个文本子节点
。如果两个文本节点是相邻的同胞节点
,那么这两个节点中的文本就会连起来显示,中间不会有空格。
var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
*规范化文本节点
normalize()
方法:
如果 在一个包含两个或多个文本节点的父元素上调用 normalize()方法,则会将所有文本节点合并成一个 节点,结果节点的 nodeValue 等于将合并前每个文本节点的 nodeValue 值拼接起来的值。
var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
var anotherTextNode = document.createTextNode("Yippee!");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
alert(element.childNodes.length); //2
element.normalize();
alert(element.childNodes.length); //1
alert(element.firstChild.nodeValue);// "Hello world!Yippee!"
* 分割文本节点
splitText()
方法:
这个方法会将一个文本节点分成两个文本节点,即按照指定的位置分割 nodeValue 值。原来的文本节点将包含从开始到指定位 置之前的内容,新文本节点将包含剩下的文本。这个方法会返回一个新文本节点,该节点与原节点的 parentNode 相同。
var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");
element.appendChild(textNode);
document.body.appendChild(element);
var newNode = element.firstChild.splitText(5);
alert(element.firstChild.nodeValue); //"Hello"
alert(newNode.nodeValue); //" world!"
alert(element.childNodes.length); //2
(5) Comment类型
注释在 DOM 中是通过 Comment 类型来表示的。
Comment 节点具有下列特征:
(1) nodeType 的值为 8;
(2) nodeName 的值为"#comment";
(3) nodeValue 的值是注释的内容;
(4) parentNode 可能是 Document 或 Element;
(5) 不支持(没有)子节点。
-
Comment 类型与 Text 类型继承自相同的基类,因此它拥有除 splitText()之外的所有字符串操作方法。
-
与 Text 类型相似,也可以通过
nodeValue
或data 属性
来取得注释的内容。
3.document.createComment()
并为其传递注释文本也可以创建注释节点。
(6) CDATASection类型
- CDATASection 类型只针对
基于 XML 的文档
,表示的是 CDATA 区域。 - 与 Comment 类似, CDATASection 类型继承自 Text 类型,因此拥有除 splitText()之外的所有字符串操作方法。
CDATASection 节点具有下列特征:
(1) nodeType 的值为 4;
(2) nodeName 的值为"#cdata-section";
(3) nodeValue 的值是 CDATA 区域中的内容;
(4) parentNode 可能是 Document 或 Element; 不支持(没有)子节点。
-
CDATA 区域只会出现在 XML 文档中,因此多数浏览器都会把 CDATA 区域
错误地解析为 Comment 或 Element
。 -
在真正的 XML 文档中,可以使用
document.createCDataSection()
来创建 CDATA 区域,只需 为其传入节点的内容即可。
(7) DocumentType类型
DocumentType 包含着与文档的 doctype 有关的所有信息。
DocumentType具有下列特征:
(1) nodeType 的值为 10;
(2) nodeName 的值为 doctype 的名称;
(3) nodeValue 的值为 null;
(4) parentNode 是 Document;
(5) 不支持(没有)子节点。
- 在 DOM1 级中,DocumentType 对象
不能动态创建
,而只能通过解析文档代码的方式来创建。 - 支持它的浏览器会把 DocumentType 对象保存在
document.doctype
中。 - DOM1 级描述了 DocumentType 对象的
3 个属性
:name、entities 和 notations。
(1)
name
表示文档类型的名称。
(2) entities 是由文档类型描述的实体的 NamedNodeMap 对象
(3) notations 是由文档类型描述的符号的 NamedNodeMap 对象。
* DocumentFragment类型
- 在所有节点类型中,只有 DocumentFragment 在文档中
没有对应的标记
。 - DOM 规定文档片段 (document fragment)是一种“轻量级”的文档,可以包含和控制节点,但不会像完整的文档那样占用
额外的资源。
DocumentFragment 节点具有下列特征:
(1) nodeType 的值为 11;
(2) nodeName 的值为"#document-fragment";
(3) nodeValue 的值为 null;
(4) parentNode 的值为 null;
(5) 子节点可以是 Element、ProcessingInstruction 、Comment、Text、CDATASection 或EntityReference。
- 虽然不能把文档片段直接添加到文档中,但可以将它作为一个“仓库”来使用,即可以在里面保存将来可能会添加到文档中的节点。
document.createDocumentFragment()方法
:创建文档片段。
var fragment = document.createDocumentFragment();
- 如果将文档中的节点添加到文档片段中,就会从文档树中移除该节点,也不会从浏览器中再看到该节点。添加到文档片段 中的新节点同样也不属于文档树。
- 可以通过 appendChild()或 insertBefore()将文档片段中内容添 加到文档中。在将文档片段作为参数传递给这两个方法时,实际上
只会将文档片段的所有子节点添加到相应位置上
;文档片段本身永远不会成为文档树的一部分。
(5) Attr类型
元素的特性在 DOM 中以 Attr 类型来表示。
- 从技术角度讲,特性就是存在于元素的 attributes 属性中的节点。
特性节点具有 下列特征:
(1) nodeType 的值为 2;
(2) nodeName 的值是特性的名称;
(3) nodeValue 的值是特性的值;
(4) parentNode 的值为 null;
(5) 在 HTML 中不支持(没有)子节点;
(6) 在 XML 中子节点可以是 Text 或 EntityReference。
-
尽管它们也是节点,但特性却不被认为是 DOM 文档树的一部分。
-
Attr 对象有
3 个属性
:name、value 和 specified。
(1) name 是特性名称(与 nodeName 的 值相同)。
(2) value 是特性的值(与 nodeValue 的值相同)。
(3) specified 是一个布尔值,用以区别特性是在代码中指定的,还是默认的。
document.createAttribute()
并传入特性的名称可以创建新的特性节点。
setAttributeNode()
方法:将新创建的特性添加到元素中。
访问特性:
attributes 属性、getAttributeNode()方法以及 getAttribute()方法。其中,attributes和 getAttributeNode()都会返回对应特性的 Attr 节点,而 getAttribute()则只返回特性的值。
var attr = document.createAttribute("align");
attr.value = "left";
element.setAttributeNode(attr);
alert(element.attributes["align"].value);//"left"
alert(element.getAttributeNode("align").value); //"left"
alert(element.getAttribute("align")); //"left"
2. DOM 操作技术
(1) 动态脚本
创建动态脚本有两种方式:插入外部文件
和直接插入 JavaScript 代码
。
* 加载外部的 JavaScript 文件
function loadScript(url){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script);
}
loadScript("client.js");
* 指定 JavaScript 代码
function loadScriptString(code){
var script = document.createElement("script");
script.type = "text/javascript";
try {
script.appendChild(document.createTextNode(code));
} catch (ex){
script.text = code;
}
document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");
IE 将<script>视为一个特殊的元素,不允许 DOM 访问其子节点。不过,可以使用<script>元素的
text 属性
来指定 JavaScript 代码。
(2) 动态样式
与动态脚本类似,所谓动态样式是指在页面刚加载时不存在的样式;动态样式是在页面加载完成后动态添加到页面中的。
- 能够把 CSS 样式包含到 HTML 页面中的元素有两个。其中,
<link>元素
用于包含来自外部的文件, 而<style>元素
用于指定嵌入的样式。
*<link>元素
<link rel="stylesheet" type="text/css" href="styles.css">
function loadStyles(url){
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = url;
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
loadStyles("styles.css");
* <style>元素
<style type="text/css">
body {
background-color: red;
}
</style>
function loadStyleString(css){
var style = document.createElement("style");
style.type = "text/css";
try{
style.appendChild(document.createTextNode(css));
} catch (ex){
style.styleSheet.cssText = css;
}
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body{background-color:red}");
IE 将<style>视为 一个特殊的、与<script>类似的节点,不允许访问其子节点。解决 IE 中这个问题的办法,就是访问元素的 styleSheet 属性, 该属性又有一个 cssText 属性,可以接受 CSS 代码。
(3) 操作表格
*<table>元素添加的属性和方法
(1) caption:保存着对<caption>元素(如果有)的指针。
(2) tBodies:是一个<tbody>元素的 HTMLCollection。
(3) tFoot:保存着对<tfoot>元素(如果有)的指针。
(4) tHead:保存着对<thead>元素(如果有)的指针。
(5) rows:是一个表格中所有行的 HTMLCollection。
(6) createTHead():创建<thead>元素,将其放到表格中,返回引用。
(7) createTFoot():创建<tfoot>元素,将其放到表格中,返回引用。
(8) createCaption():创建<caption>元素,将其放到表格中,返回引用。 deleteTHead():删除<thead>元素。
(9) deleteTFoot():删除<tfoot>元素。
(10) deleteCaption():删除<caption>元素。
(11) deleteRow(pos):删除指定位置的行。
(12) insertRow(pos):向 rows 集合中的指定位置插入一行。
*为<tbody>元素添加的属性和方法
(1) rows:保存着<tbody>元素中行的 HTMLCollection。
(2) deleteRow(pos):删除指定位置的行。
(3) insertRow(pos):向 rows 集合中的指定位置插入一行,返回对新插入行的引用。
*<tr>元素添加的属性和方法
(1) cells:保存着<tr>元素中单元格的 HTMLCollection。
(2) deleteCell(pos):删除指定位置的单元格。
(3) insertCell(pos):向 cells 集合中的指定位置插入一个单元格,返回对新插入单元格的引用。
<table border="1" width="100%">
<tbody>
<tr>
<td>Cell 1,1</td>
<td>Cell 2,1</td>
</tr>
<tr>
<td>Cell 1,2</td>
<td>Cell 2,2</td>
</tr>
</tbody>
</table>
//创建 table
var table = document.createElement("table");
table.border = 1;
table.width = "100%";
//创建 tbody
var tbody = document.createElement("tbody");
table.appendChild(tbody);
//创建第一行
tbody.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));
//创建第二行
tbody.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));
//将表格添加到文档主体中
document.body.appendChild(table);
(4) 使用NodeList
NodeList 及其“近亲”NamedNodeMap 和 HTMLCollection,这三个集合都是“动态的”;换句话说,每当文档结构发生变化时,它们都会得到更新。因 此,它们始终都会保存着最新、最准确的信息。
如果想要迭代一个 NodeList,最好是使用 length 属性初始化第二个变量,然后将迭代器与该变量进行比较。
var divs = document.getElementsByTagName("div"),i,len, div;
for (i=0, len=divs.length; i < len; i++){
div = document.createElement("div");
document.body.appendChild(div);
}
网友评论