DOM 会将任意的 HTML 或 XML 文档描绘成由多节点构成的结构。即表现为以一个特定节点为根节点的树型结构:
比如下面这个 HTML:
<html> <head> <title>Sample Page</title> </head> <body> <p>Hello World!</p> </body> </html>这个例子中的 <html> 元素称为文档元素,是文档最外层的元素。XML 中没有预定义的元素,所以任何元素都可能称为文档元素。
这个例子可以表示为一个层次结构:
DOM1 级定义了 Node 接口,它由 DOM 中的所有节点类型实现。在 JavaScript 中是作为 Node 类型实现的;除了 IE,其他类型的浏览器都可以访问这个类型。JavaScript 中的所有节点类型都继承自 Node 类型,因此所有节点类型都共享着相同的基本属性和方法。
每个节点都有 nodeType 属性,表示节点的类型,有 12 种,是用 Node 类型中定义的数值常量来表示的:
* 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)通过比较,可以确定节点的类型:
if (someNode.nodeType == Node.ELEMENT_NODE){//IE 中无效 console.log("Node is an element."); }为了跨浏览器实现,最好是跟节点类型的数值进行比较:
if (someNode.nodeType == 1){//跨浏览器 console.log("Node is an element."); }在使用之前,最好先检测一下节点的类型:
if (someNode.nodeType == 1){ value = someNode.nodeName;//取得元素的标签名 }对于元素节点,nodeName 表示的是元素的标签名,nodeValue 返回 null。
节点之间的各种关系,可以用传统的家族关系来描述,把文档树比喻为家谱。
每个节点都有一个 childNodes 属性,它保存着一个 NodeList 对象。NodeList 对象是一种类数组对象,保存了一组有序的节点,可以通过位置来访问这些节点。注意,它不是 Array 的实例。 NodeList 对象是基于 DOM 结构动态查询的结果,也就是说,DOM 结构的变化会自动反映在 NodeList 对象中。
可以这样访问保存在 NodeList 中的节点:
var firstChild = someNode.childNodes[0];//方括号方式 var secondChild = someNode.childNodes.item(1);//item() var count = someNode.childNodes.length;//节点数量可以将 NodeList 转换为数组(跨浏览器):
/** * 把 NodeList 对象转换为数组 * @param nodes * @returns {*} */ 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 列表中的所有节点都有相同的父节点。列表中的每个节点都有 previousSibling 和 nextSibling 属性,它们可以访问同一列表中的其他节点:
if (someNode.nextSibling === null){ console.log("childNodes 中最后一个节点") } else if (someNode.previousSibling === null){ console.log("childNodes 中第一个节点") }如果列表中只有一个节点,那么它的 previousSibling 和 nextSibling 都为 null。具体关系如下图:
还有一个 hasChildNodes() 方法,如果节点包含一个或者多个子节点的情况下,它会返回 true。
节点还有一个属性是 ownerDocument,它指向整个文档的文档节点,通过它,我们可以直接访问文档节点。
注意: 所有节点类型都继承自 Node,但不是所有类型的节点都有子节点(以后会做详细说明)。
因为关系指针都是只读的,所以 DOM 提供了一些操作节点的方法。
appendChild() ,它向 childNodes 列表的末尾添加一个节点,然后返回这个新节点:
var returnNode = someNode.appendChild(newNode); console.log(returnNode == newNode);//true console.log(someNode.lastChild == newNode);//true如果传入到 appendChild() 方法的节点已经是文档的一部分,那么就将这个节点从原来的位置移动到新位置。因此如果把父节点中的第一个子节点传入 appendChild() 方法,那么它就会成为这个父节点的最后一个子节点:
//someNode 有多个子节点 var returnedNode = someNode.appendChild(someNode.firstChild); console.log(returnNode == someNode.firstChild);//false console.log(returnNode == someNode.lastChild);//true会把节点插入到参照节点的前一个同胞节点。
输入参数:
要插入的节点。作为参照的节点。如果参照节点是 null,则功能与 appendChild() 相同。
//插入后成为最后一个子节点 returnNode = someNode.insertBefore(newNode, null); console.log(newNode == someNode.lastChild);//true //插入后成为第一个子节点 var returnNode = someNode.insertBefore(newNode, someNode.firstChild); console.log(returnNode == newNode);//true console.log(returnNode == someNode.firstChild);//true //插入到最后一个子节点前面 returnNode = someNode.insertBefore(newNode, someNode.lastChild); console.log(newNode == someNode.childNodes[someNode.childNodes.length-2]);//true从文档树中移除要替换的节点,把要插入的节点放在这个位置。
输入参数:
要插入的节点。要替换的节点。 //替换第一个子节点 var returnedNode = someNode.replaceChild(newNode, someNode.firstChild); //替换最后一个子节点 returnedNode = someNode.replaceChild(newNode, someNode.lastChild);只是移除输入的节点,但这个节点仍然为文档树所有,只是它没有了自己的位置。
注意: 以上介绍的四种方法,都是针对某个节点的子节点进行操作,所以如果在不支持子节点的节点上调用这些方法,就会抛出错误。
创建节点的一个完全相同的副本。
它只有一个参数,是否执行深度复制:
true,深度复制,即复制节点以及整个子节点树。false, 浅复制,即只复制节点本身。复制后的节点为文档所有,但它与文档树中的其他节点没有任何关系,除非使用操作方法把它添加到文档中。
假设原先的文档是这样的:
<ul> <li>item 1</li> <li>item 2</li> <li>item 3</li> </ul>假设已经把 <ul> 元素的引用赋值给了 myList 中:
var deepList = myList.cloneNode(true);//深度复制 console.log(deepList.childNodes.length);//3 (IE < 9) 或 7(其他浏览器) var shallowList = myList.cloneNode(false);//钱复制 console.log(shallowList.childNodes.length);//0因为 IE9 之前的版本不会为空白符创建节点,所以它统计到的值比其他浏览器来的小。
注意: cloneNode() 不会复制添加到 DOM 节点中的 JavaScript 属性(比如事件处理程序)。它只复制特性、子节点(深度复制),其他都不会被复制。IE 存在一个 bug,它会复制事件处理程序。所以我们最好在复制之前先移除上面的事件处理程序,保证跨浏览器的一致性。
它用于处理文档树中的文本节点。在某个节点上调用该方法时,会删除找到的空文本节点,将找到的相邻文本节点合并为一个文本节点。
JavaScript 是通过 Document 类型来表示文档。在浏览器中,document 对象是 HTMLDocument 的一个实例,表示整个 HTML 页面。而且 document 对象是 window 对象的一个属性,所以可以作为全局对象来访问。
属性名称属性值nodeType9nodeNamedocumentnodeValuenullparentNodenullownerDocumentnull它的子节点可能是 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction 或 Comment。
Document 类型表示 HTML 页面或者 XML 文档。它最常用于 HTMLDocument 实例的 document 对象。通过它,不仅可以取得与页面有关的信息,还可以操作页面的外观以及底层结构。
注意: 在所有浏览器(包括 IE8 以及后续版本)都可以访问 HTMLDocument 类型的构造函数和原型,但只有在 Firefox、Safari、Chrome 和 Opera 中,才能通过脚本访问 Document 类型的构造函数和原型。
documentElement 属性会指向 HTML 页面中的 <html> 元素。比如有这样的页面:
<html> <body> </body> </html>可以这样访问到 <html> 元素:
var html = document.documentElement;//取得 <html> 的引用 console.log(html === document.childNodes[0]);//true console.log(html === document.firstChild);//true所有浏览器都支持。
body 属性指向 <body> 元素:
var body = document.body;
所有浏览器都支持。
用于访问 <!DOCTYPE> 标签的信息。
因为浏览器对这个属性支持的差别很大,所以它的用处很有限。
因为 document 对象是 HTMLDocument 的实例,所以还有一些 Document 对象所没有的属性。
可以取得或者修改当前页面的标题,即浏览器窗口的标题栏或者标签页上的文本。
var originalTitle = document.title;//取得标题 document.title = "New page title";//设置标题所有这些属性信息都存于请求的 HTTP 头部。
只有 domain 属性是可以设置的,但因为安全方面的原因,如果 URL 中包含一个子域名,比如map.baidu.com,那么就只能将 domain 设置为 baidu.com,而不能把这个属性设置为 URL 中不包含的域名。
当页面中包含来自其他子域框架的时候,因为跨域安全限制,它们无法通过 JavaScript 通信,这时就可以把 domain 属性设置为相同的值,这样就可以相互访问咯。
domain 属性还有一个限制:如果域名一开始设置为是大范围的,那么不能再次把它设置为小范围的。
//假设当前页面是 map.baidu.com document.domain = "baidu.com";//成功 document.domain = "map.baidu.com";//失败所有浏览器都有这一限制。
输入参数:要取得元素的ID。严格匹配,区分大小写。IE8 及较低版本不区分大小写。
返回:如果找到,就返回该元素;如果不存在,则返回 null。
输入参数:要取得元素的标签名。 返回:包含零或多个元素的 NodeList。在 HTML 文档中,会返回 HTMLCollection 对象,它也是一个动态获取的集合。
var images = document.getElementsByTagName("img"); console.log(images.length);//图片数量 console.log(images[0].src);//输出第一个图像元素的 src 特性 console.log(images.item(0).src);//输出第一个图像元素的 src 特性HTMLCollection 对象还有一个 namedItem() 方法,它可以通过元素的 name 属性取得集合中的项:
<img src="myimage.gif" name="myImage"> var myImage = images.namedItem("myImage"); myImage = images["myImage"];//也可以使用方括号语法这样可以取得文档中的所有元素,按照元素的先后顺序(因为 IE 将注释解释为元素,所以它会带上所有的注释节点):
var allElements = document.getElementsByTagName("*");注意: 虽然标准规定标签名要区分大小写,但为了最大限度与既有的 HTML 页面兼容,传给getElementsByTagName() 的参数是无需区分大小写的。但对于 XML 文档(包括 XHTML),还是需要区分大小写。
只有 HTMLDocument 才有的方法。
输入参数:标签的 name 属性。 返回:带有给定 name 属性的所有元素。
最常用于单选按钮:
<ul> <li><input type="radio" value="red" name="color" id="colorRed"> <label for="colorRed">red</label></li> <li><input type="radio" value="green" name="color" id="colorGreen"> <label for="colorGreen">green</label></li> <li><input type="radio" value="blue" name="color" id="colorBlue"> <label for="colorBlue">blue</label></li> </ul>所有的单选按钮的 name 值都是 color,但 ID 不同,这样可以确保只有一个值被发送给服务器。
var radios = document.getElementsByName("color");对于单选按钮来说,namedItem() 只会取得第一项的元素。
这些都是 HTMLDocument 对象,它们为访问文档的常用部分提供了便捷的方法:
集合方法说明document.anchors所有带有 name 属性的 <a> 元素document.applets所有 <applet> 元素。不建议使用document.forms所有 <form> 元素。即 document.getElementsByTagName(“form”)。document.images所有 <img> 元素。即 document.getElementsByTagName(“img”)。document.links所有带有 <href> 属性的 <a> 元素。它们都会随着当前文档内容的更新而更新。
DOM1 级中的 document.implementation 有一个 hasFeature() 方法。
输入参数:
要检测的 DOM 的功能名称版本号返回:如果浏览器支持给定名称和版本的功能,就会返回 true。
var hasXmlDom = document.implementation.hasFeature("XML", "1.0"); 功能版本号说明Core1.0、2.0、3.0核心 DOM,表现文档的节点数。XML1.0、2.0、3.0Core 的 XML 扩展,添加了对 CDATA、处理指令以及实体的支持HTML1.0、2.0XML 的 HTML 扩展,,添加了对 HTML特有元素以及实体的支持Views2.0基于某些样式完成文档的格式化StyleSheets2.0将样式表关联到文档CSS2.0对层叠样式表 1 级的支持CSS22.0对层叠样式表 2 级的支持Events2.0、3.0常规 DOM 事件UIEvents2.0、3.0用户界面事件MouseEvents2.0、3.0由鼠标引发的事件MutationEvents2.0、3.0DOM 树变化引发的事件HTMLEvents2.0HTML4.01 事件Range2.0用于操作 DOM 树中某个范围的对象和方法Traversal2.0遍历 DOM 树的方法LS3.0文件与 DOM 树之间的同步加载和保存LS-Async3.0文件与 DOM 树之间的异步加载和保存Validation3.0在确保有效的前提下修改 DOM 树的方法要注意,即使 hasFeature 返回 true,也不意味着真是实现了该规范。 Safari 2.x 及更早的版本会在没有完全实现某些 DOM 功能的情况下也会返回 true。因此在使用 hasFeature() 之外,同时还能使用能力检测。
就是将文档写入到网页中,有四种方法。
write(),接受一个字符串参数,即要写入到输出流中的文本。writeln(),与 write() 功能相同,只是它会在字符串的末尾添加一个换行符(\n)。利用这两种方法,可以向页面动态地加入内容:
document.write("<strong>" + (new Date()).toString() + "</strong>");也可以利用这两种方法,让页面动态包含外部的资源,比如 JavaScript 文件。但不能直接包含字符串 </script>,因为这会导致该字符串被解释为脚本块的结束,必须把它分开写,像这样:
document.write("<script type=\"text/javascript\" src=\"file.js\">" + "<\/script>");如果在文档加载结束后,再调用 document.write(),那么输出的内容就会重写整个页面:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>文档加载结束后再调用 document.write,会重写整个页面</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() ,是不需要用到上面这两种方法的。
注意: 严格型 XHTML 文档以及那些按照 application/xml+xhtml 内容类型提供的页面,它们不支持文档写入。
Element 类型用于表现 XML 或 HTML 元素,它提供了对元素标签名、子节点以及特性的访问。
属性名称属性值nodeType1nodeName元素的标签名nodeValuenullparentNodeDocument 或 Element子节点可能是 Element、Text、Comment、ProcessingInstruction、CDATASection 或 EntityReference。可以使用 nodeName 属性或者 tagName 属性来访问元素的标签名,它们会返回相同的值。建议使用 tagName ,因为它字面表达的更清晰。
假设页面上有这样一个元素:
<div id="myDiv"></div>可以这样取得这个元素以及标签名:
var div = document.getElementById("myDiv"); console.log(div.tagName);//DIV console.log(div.tagName == div.nodeName);//true在 HTML 中标签名始终都是大写,在 XML(XHTML)中,标签名与源代码的一致。如果不确定脚本是将在 HTML 中还是 XML 中执行,最好在比较前先将标签名转换为相同的大小写形式:
if (element.tagName.toLowerCase() == "div"){ ... }注意: 在 Safari2 之前的版本以及 Opera 8 之前的版本,不能访问 Element 类型的构造函数,其他浏览器都能通过脚本访问 Element 类型的构造函数及原型。
每个 HTML 元素都存在下列标准特性:
属性名称属性值id元素在文档中的唯一标识符title附加说明,一般通过工具提示条显示出来lang语言代码,很少使用dir语言的方向;ltr:left-to-right,从左到右;rtl:right-to-left,从右到左,很少使用className为元素指定的 CSS 类,因为 class 是 JavaScript 的保留字,所以没有使用这一名字。元素中的这些特性既可以取得,也可以设置:
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr"></div> <script type="text/javascript"> var div = document.getElementById("myDiv"); console.log(div.id);//myDiv console.log(div.className);//bd console.log(div.title);//Body text console.log(div.lang);//en console.log(div.dir);//ltr div.id = "someOtherId"; div.className = "ft"; div.title = "Some other text"; div.lang = "fr"; div.dir = "rtl"; </script>对 dir 的修改,会立即影响页面中文本的左、右对齐方式。
注意,传递给 getAttribute() 方法的特性名必须与实际的特性名一致,比如这里传入的是 class,而不是 className。如果给定的特性不存在,会返回 null。
通过 getAttribute() 也可以取得自定义特性的值,根据 HTML5 的规范,自定义特性应该在名字前加上 data- 前缀。
只有非自定义的特性才会以属性的形式被添加到 DOM 对象中,在早期的 IE 中却会为自定义的特性创建属性,IE10 修正了过来:
<div id="myDiv" align="left" my_special_attribute="hello!"></div> <script type="text/javascript"> var div=document.getElementById("myDiv"); console.log(div.id);//myDiv console.log(div.align);//left console.log(div.my_special_attribute);//undefined(早期的 IE 除外,实测 IE10 返回的也是 undefined) </script>有两类特殊的属性,通过属性的值与通过 getAttribute() 返回的值不相同:
属性名说明属性的值getAttribute() 返回的值style为元素指定的样式对象CSS 文本onclick点击事件处理程序JavaScript 函数JavaScript 函数的代码因为这些差异,开发人员一般只使用对象的属性,只有为了取得自定义属性的值,才使用 getAttribute() 方法。
getAttribute(),接受两个参数:
要设置的特性名要设置的特性值如果特性已经存在,会用新值替换旧值;如果特性不存在,就会创建这个特性并设置它的值:
div.setAttribute("id", "someOtherId"); div.setAttribute("class", "ft"); div.setAttribute("title", "Some other text"); div.setAttribute("lang", "fr"); div.setAttribute("dir", "rtl");setAttribute() 既可以操作 HTML 的特性,也可以操作自定义的特性。它会把特性名统一转换为小写形式。
可以直接给属性赋值,但不能直接给自定义的属性赋值:
//直接给属性赋值 div.id = "someOtherId"; div.align = "left"; //这样添加的一个自定义属性,不会自动成为元素的属性 div.mycolor = "red"; console.log(div.getAttribute("mycolor"));//null(老版本的 IE 除外,实测 IE10 返回的也是 null)注意: 在 IE7 及之前的版本中,setAttribute() 存在异常行为。使用它来设置 class 、style 特性以及事件处理程序,没有效果,IE8修复了这些问题。
Element 类型是使用 attributes 属性的唯一一个 DOM 节点类型。attributes 属性中包含一个 NamedNodeMap,也是一个 “动态” 集合。元素的每一个特性都由一个 Attr 节点表示,每个节点都保存在 NamedNodeMap 对象中。NamedNodeMap 对象拥有以下方法:
方法名称说明getNamedItem(name)返回 nodeName 属性等于 name 的节点。removeNamedItem(name)从列表中移除 nodeName 属性等于 name 的节点。setNamedItem(node)向列表中添加节点,以节点 nodeName 属性为索引。item(pos)返回位于 pos 处的节点。节点的 nodeValue 就是特性的值,比如要取得元素的 id 特性:
var id = element.attributes.getNamedItem("id").nodeValue;也可以使用方括号语法获取或设置值:
var id = element.attributes.["id"].nodeValue; element.attributes.["id"].nodeValue = "someOtherId";removeNamedItem(name) 与 在元素上调用 removeAttribute() 效果相同,都是直接删除给定名称的特性。它们的区别是,removeNamedItem(name) 会返回被删除特性的 Attr 节点。
由于 attributes 属性没有之前介绍的 getAttribute()、removeAttribute() 以及 setAttribute() 来的方便,所以开发人员更喜欢使用后面的方法。
attributes 属性更多用于遍历元素的特性上。比如需要将 DOM 结构序列化为 XML 或 HTML 字符串时,就会需要遍历元素的特性:
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; pairs.push(attrName + "=\"" + attrValue + "\"");//返回 name="value" ... } return pairs.join(" "); } console.log(outputAttributes(document.getElementById("myDiv")));这个函数使用一个数组来保存名值对,并以空格作为它的分隔符。
针对 attributes 对象中的特性,不同浏览器返回的顺序是不同的。IE7 以及早期版本会返回 HTML 元素中所有可能的特性。因此我们可以对这个函数进行改进,让它只返回指定的特性。每个特性节点都有一个 specified 属性,如果为 true,表示在 HTML 中指定了该特性,或者是通过 setAttribute() 设置了该特性,所以我们可以利用这个属性进行过滤:
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){//确保IE7 以及更早的版本,也只返回指定的特性 pairs.push(attrName + "=\"" + attrValue + "\""); } } return pairs.join(" "); } console.log(outputAttributes(document.getElementById("myDiv")));document.createElement(),接受一个参数,即要创建元素的标签名。这个标签名在 HTML 文档中不区分大小写,但在 XML 文档中是区分大小写的!
var div = document.createElement("div"); //创建后,就可以操作元素的特性咯 div.id = "myDiv"; div.className = "box"; document.body.appendChild(div);//添加到文档树在 IE 中可以使用 createElement(),可以传入完整的元素标签:
document.createElement("<div id=\"myNewDiv\" class=\"box\"></div>");这可以解决 IE7 以及早期版本在动态创建元素上的一些问题:
不能设置动态创建的 <iframe> 元素的 name 属性。不能通过表单的 reset() 方法重设动态创建的 元素。动态创建的 type=reset 的 <button> 元素无法重设表单。动态创建的一批 name 相同的单选按钮彼此毫无联系。 if (client.browser.ie && client.browser.ie <=7){ //创建带 name 属性的 iframe 元素 var iframe = document.createElement("<iframe name=\"myframe\"></iframe>"); //创建 input 元素 var input = document.createElement("<input type=\"checkbox\">"); //创建 button 元素 var button = document.createElement("<button type=\"reset\"></button>"); //创建单选按钮 var radio1 = document.createElement("<input type=\"radio\" name=\"choice\" + "value=\"1\">"); var radio2 = document.createElement("<input type=\"radio\" name=\"choice\" + "value=\"2\">"); }因为要用到浏览器检测,所以建议只在 IE7 以及早期版本存在上述问题的情况下再使用。
元素可以有任意个数的子节点以及后代节点。这些子节点可能是元素、文本节点、注释或处理指令。
<ul id="myList> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul>IE 会认为这段代码中的 ul 拥有 3 个子节点(li)。其他浏览器则认为 ul 拥有 7 个子节(3 个 li,4 个分隔 li 的空白文本节点),所以在迭代时,需要先检测一下 nodeType 属性:
for (var i=0, len=element.childNodes.length; i < len; i++){ if (element.childNodes[i].nodeType == 1){//是元素节点 ... } }getElementsByTagName() 会根据特定的标签名取得子节点或者后代节点,它会从当前元素开始搜索,即只会返回当前元素的后代:
var ul = document.getElementById("myList"); var items = ul.getElementsByTagName("li");//如果 ul 包含更多层次的后代元素,那么各个层次中的 li 元素也会返回指的是村文本内容,也可以包含转义后的 HTML 字符。
属性名称属性值nodeType3nodeNametextnodeValue节点所包含的文本parentNodeElement子节点没有有这些方法可以操作节点中的文本:
方法名说明appendData(text)将 text 添加到节点的末尾。deleteData(offset, count)从 offset 指定的位置开始删除 count 个字符。insertData(offset, text)在 offset 指定的位置插入 text。replaceData(offset, count, text)用 text 替换从 offset 指定的位置开始到 offset+count 为止处的文本。splitText(offset)从 offset 指定的位置将当前文本节点分为两个文本节点。substringData(offset, count)提取从 offset 指定的位置开始到 offset+count 为止处的字符串。length 属性表示的是节点中字符的个数。
默认情况下,每个可以包含内容的元素只能有一个文本节点,而且必须确实有内容存在:
<div></div><!-- 没有内容,所以没有文本节点--> <div> </div><!-- 有空格,所以有一个文本节点--> <div>Hello</div><!-- 有内容,所以有一个文本节点-->这样访问或者修改文本节点:
<div id="deniro">message</div> <script type="text/javascript"> var div = document.getElementById("deniro"); var textNode = div.firstChild;//或者 div.childNodes[0] div.firstChild.nodeValue="Some other message"; </script>createTextNode() 创建新文本节点,它接受一个参数,即要插入节点中的文本:
var element=document.createElement("div"); element.className="message"; var textNode=document.createTextNode("Hello world!"); element.appendChild(textNode); document.body.appendChild(element);一般来说,每个元素只有一个文本子节点。不过也可以包含多个文本节点:
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():如果在一个包含超过一个文本节点的父节点上调用该方法,那么所有的文本节点就会合并为一个节点:
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); console.log(element.childNodes.length);//2 element.normalize(); console.log(element.childNodes.length);//1 console.log(element.firstChild.nodeValue);//Hello world!Yippee!注意: 在某些情况下,在 IE6 下执行 normalize 方法会导致浏览器崩溃!IE7 修复了这一问题。
splitText():会按照指定的位置,将一个文本节点分为两个。它会返回新文本节点(即分割后的第二个节点):
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); console.log(element.firstChild.nodeValue);//"Hello" console.log(newNode.nodeValue);//" world!" console.log(element.childNodes.length);//2分割文本节点是一种从文本节点中提取数据的常用方法。
可以通过父节点来访问注释节点:
<div id="myDiv"><!-- A comment --></div> <script type="text/javascript"> var div = document.getElementById("myDiv"); var comment = div.firstChild; console.log(comment.data);//A comment </script>创建注释节点:
var comment = document.createComment("A comment ");注意:浏览器不会识别位于 </html>标签之后的注释。所以如果要访问,一定要保证注释节点是 </html> 的后代。
CDATASection 类型只针对 XML 文档,它继承自 Text 类型。
属性名称属性值nodeType4nodeNamecdata-sectionnodeValueCDATA 区域中的内容parentNodeDocument 或 Element子节点没有Firefox、Safari、Opera以及 Chrome 4.0 支持这个类型。
属性名称属性值nodeType10nodeNamedoctype 名称nodeValuenullparentNodeDocument子节点没有在 DOM1 级中,只能通过解析文档代码的方式创建。它有三个属性:
属性名称说明name文档类型的名称,即出现在 <!DOCTYPE 后面的文本entitiesNamedNodeMap 对象(文档描述)notationsNamedNodeMap 对象(符号)其实只有 name 是真正有用的。
以严格型的 HTML 4.01 的文档声明为例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01/EN" "http://www.w3.org/TR/html4/strict.dtd"> document.doctype.name;//HTML它在文档中没有对应的标签。它可以包含和控制节点,但不会占用额外的资源:
属性名称属性值nodeType11nodeNamedocument-fragmentnodeValuenullparentNodenull子节点可以是 Element、ProcessingInstruction、Comment、Text、CDATASection 或 EntityReference它可以作为一个仓库,在这里保存将来会添加到文档中的节点。如果将文档中的节点添加到了文档片段中,那么就会从文档树中移除该节点。可以通过 appendChild() 或 insertBefore() 将文档片段上的所有子节点都添加到相应的位置上。利用这种技术可以一次性把多个元素添加到文档中,避免了浏览器在一个一个元素添加时的反复渲染问题:
<ul id="myList"></ul> <script type="text/javascript"> var fragment=document.createDocumentFragment(); var ul=document.getElementById("myList"); var li=null; for(var i=0;i<3;i++){ li=document.createElement("li"); li.appendChild(document.createTextNode("Item "+(i+1))); fragment.appendChild(li); } ul.appendChild(fragment); </script>表示的是元素的属性,所有的浏览器都可以访问 Attr 类的构造函数和原型。
属性名称属性值nodeType11nodeName特性的名称nodeValue特性的值parentNodenull子节点HTML 中没有,XML中是 Text 或 EntityReference一般开发中很少使用这个类型。
Attr 对象有三个属性:
属性名称属性值name属性名称value属性值spe cified | 布尔值,是在代码中指定还是默认
<div id="myDiv"></div> <script type="text/javascript"> var element = document.getElementById("myDiv"); var attr = document.createAttribute("align"); attr.value = "left"; element.setAttributeNode(attr); console.log(element.attributes["align"].value);//left console.log(element.getAttributeNode("align").value);//left console.log(element.getAttribute("align"));//left </script>注意: 使用 getAttribute()、setAttribute() 和 removeAttribue() 操作节点的属性更方便!