10.1 节点层次
文档节点是每个文档的根节点。文档节点只有一个子节点,即
元素,我们称之为文档元素,文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在HTML页面中,文档元素始终都是
元素
10.1.1 Node类型
JavaScript中的所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。每个节点都有一个NodeType属性
//也可以是someNode.nodeType == Node.ELEMENT_NODE,但为了确保跨浏览器兼容,最好还是将 nodeType 属性与数字值进行比较
if(someNote.nodeType == 1){
alert('Node is an element')
}
1. nodeName和nodeValue属性
对于元素节点, nodeName 中保存的始终都是元素的标签名,而 nodeValue 的值则始终为 null 。
2.节点关系
每个节点都有一个 childNodes 属性,其中保存着一个 NodeList 对象。 NodeList 是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。请注意,虽然可以通过方括号语法来访问 NodeList 的值,而且这个对象也有 length 属性,但它并不是 Array 的实例。
保存在NodeList中的节点可以通过方括号,也可以使用item()方法来访问
var firstChild = someNode.childNodes[0];
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
//在 IE8 及之前版本中无效
//对 arguments 对象使用 Array.prototype.slice() 方法也可以将其转换为数组
var arrayOfNodes = Array.prototype.slice.call(someNode.childNodes,0);
3. 访问节点
- parentNode
- childNodes
- previousSibling和nextSibling
if (someNode.nextSibling === null){
alert("Last node in the parent’s childNodes list.");
} else if (someNode.previousSibling === null){
alert("First node in the parent’s childNodes list.");
}
- firstChild和lastChild
如果没有子节点,那么 firstChild 和 lastChild 的值为 null
- hasChildNodes()
这个方法在节点包含一或多个子节点的情况下返回 true ;这是比查询 childNodes列表的 length 属性更简单的方法
- ownerDocument
该属性指向表示整个文档的文档节点
4. 操作节点
- appendChild()
用于向 childNodes 列表的末尾添加一个节点, 返回新增的节点
var returnedNode = someNode.appendChild(newNode);
alert(returnedNode == newNode); //true
alert(someNode.lastChild == newNode); //true
如果在调用 appendChild() 时传入了父节点的第一个子节点,那么
该节点就会成为父节点的最后一个子节点
//someNode 有多个子节点
var returnedNode = someNode.appendChild(someNode.firstChild);
alert(returnedNode == someNode.firstChild); //false
alert(returnedNode == someNode.lastChild); //true
- insertBefore()
这个方法接受两个参数:要插入的节点和作为参照的节点。插入节点后,被插入的节点会变成参照节点的前一个同胞节点( previousSibling ),同时被方法返回。如果参照节点是null ,则 insertBefore() 与 appendChild() 执行相同的操作,如下面的例子所示。
//插入后成为最后一个子节点
returnedNode = someNode.insertBefore(newNode, null);
alert(newNode == someNode.lastChild); //true
//插入后成为第一个子节点
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); //true
alert(newNode == someNode.firstChild); //true
//插入到最后一个子节点前面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length-2]); //true
- replaceChild()
前面介绍的 appendChild() 和 insertBefore() 方法都只插入节点,不会移除节点。而下面replaceChild() 方法接受的两个参数是:要插入的节点和要替换的节点。要替换的节点将由这个
方法返回并从文档树中被移除,同时由要插入的节点占据其位置。
//替换第一个子节点
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);
//替换最后一个子节点
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
- cloneNode()
用于创建调用这个方法的节点的一个完全相同的副本。 cloneNode() 方法接受一个布尔值参数,表示是否执行深复制。
10.1.2 Document 类型
nodeType的值时9,nodeValue的值是null
一般用来取得与页面有关的信息,而且还能操作页面的外观及其底层结构。
1. 文档的子节点
- documentElement属性,该属性始终指向 HTML 页面中的 元素。
var html = document.documentElement; //取得对的引用
alert(html === document.childNodes[0]); //true
alert(html === document.firstChild); //true
- 作为 HTMLDocument 的实例, document 对象还有一个 body 属性,直接指向 元素。使用频率很高
var body = document.body; //取得对的引用
所有浏览器都支持 document.documentElement 和 document.body 属性。
2. 文档信息
作为 HTMLDocument 的一个实例, document 对象还有一些标准的 Document 对象所没有的属性。这些属性提供了 document 对象所表现的网页的一些信息。
//取得文档标题
var originalTitle = document.title
//设置文档标题
var document.title = "New page title"
//取得完整的 URL
var url = document.URL;
//取得域名
var domain = document.domain;
//取得来源页面的 URL
var referrer = document.referrer;
URL 与 domain 属性是相互关联的。例如,如果 document.URL 等于 http://www.wrox.com/WileyCDA/,那么 document.domain 就等于 www.wrox.com。
3. 查找元素
getElementById()
getElementsByTagName()
这个方法接受一个参数,即要
取得元素的标签名,而返回的是包含零或多个元素的 NodeList 。
var images = document.getElementsByTagName("img")
alert(images.length); //输出图像的数量
alert(images[0].src); //输出第一个图像元素的 src 特性
alert(images.item(0).src); //输出第一个图像元素的 src 特性
- getElementsByName()
最常使用 getElementsByName() 方法的情况是取得
单选按钮;为了确保发送给浏览器的值正确无误,所有单选按钮必须具有相同的 name 特性
4. 特殊集合
- document.anchors
包含文档中所有带 name 特性的 元素
- document.forms
包含文档中所有的 元素,与 document.getElementsByTagName("form")
得到的结果相同;
document.images
包含文档中所有的元素,与 document.getElementsByTagName
("img") 得到的结果相同;document.links ,包含文档中所有带 href 特性的 元素。
这个特殊集合始终都可以通过 HTMLDocument 对象访问到,而且,与 HTMLCollection 对象类似,
集合中的项也会随着当前文档内容的更新而更新。
5. DOM一致性检测
不懂
6. 文档写入
document.write()。如果在文档
加载结束后再调用 document.write(),那么输出的内容将会重写整个页面
10.1.3 Element 类型
nodeType的值为1,nodeName 的值为元素的标签名, nodeValue 的值为 null
要访问元素的标签名,可以使用 nodeName 属性,也可以使用 tagName 属性;这两个属性会返回相同的值
1. HTML元素
//元素中指定的所有信息,都可以通过下列 JavaScript 代码取得:
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"
//当然,像下面这样通过为每个属性赋予新的值,也可以修改对应的每个特性:
div.id = "someOtherId";
div.className = "ft";
div.title = "Some other text";
div.lang = "fr";
div.dir ="rtl";
2. 取得特性
- getAttribute()
var div = document.getElementById("myDiv");
alert(div.getAttribute("id")); //"myDiv"
alert(div.getAttribute("class")); //"bd"
alert(div.getAttribute("title")); //"Body text"
alert(div.getAttribute("lang")); //"en"
alert(div.getAttribute("dir")); //"ltr"
- setAttribute()
这个方法接受两个参数:要设置的特性名和
值。如果特性已经存在, setAttribute() 会以指定的值替换现有的值;如果特性不存在, setAttribute()
则创建该属性并设置相应的值。
div.setAttribute("id", "someOtherId");
div.setAttribute("class", "ft");
div.setAttribute("title", "Some other text");
div.setAttribute("lang","fr");
div.setAttribute("dir", "rtl");
- romoveAttribute()
用于彻底删除元素的特性。调用这个方
法不仅会清除特性的值,而且也会从元素中完全删除特性
div.removeAttribute("class");
4. attributes属性
Element 类型是使用 attributes 属性的唯一一个 DOM节点类型。
属性节点和文本节点有值,而元素节点没有值
5. 创建元素
使用 document.createElement() 方法可以创建新元素。这个方法只接受一个参数,即要创建元素的标签名。
var div = document.createElement("div");
document.body.appendChild(div);
6. 元素的子节点
- Item 1
- Item 2
- Item 3
如果是 IE 来解析这些代码,那么
元素会有 3 个子节点,分别是 3 个
元素。但如果是在其
他浏览器中,元素都会有 7 个元素,包括 3 个
元素和 4 个文本节点(表示
元素之间的空
白符)。
//先检查一下 nodeTpye 属性
for (var i=0, len=element.childNodes.length; i < len; i++){
if (element.childNodes[i].nodeType == 1){
//执行某些操作
}
}
10.1.4 Text类型
- nodeType 的值为 3,nodeName 的值为 "#text",nodeValue 的值为节点所包含的文本
1. 创建文本节点
document.createTextNode()
var textNode = document.createTextNode("Hello world!");
2. 规范化文本节点
normalize()
3. 分隔文本节点
与 normalize() 相反的方法: splitText() 。这个方法会将一个文本节
点分成两个文本节点
10.1.5 Comment类型
10.1.6 CDATASection 类型
10.1.7 DocumentType 类型
10.1.8 DocumentFragment 类型
10.1.9 Attr 类型
10.2 DOM 操作技术
10.0.3 操作表格
10.3 小结
DOM 由各种节点构成,简要总结如下。
最基本的节点类型是 Node ,用于抽象地表示文档中一个独立的部分;所有其他类型都继承自
Node 。Document 类型表示整个文档,是一组分层节点的根节点。在 JavaScript 中, document 对象是Document 的一个实例。使用 document 对象,有很多种方式可以查询和取得节点。
Element 节点表示文档中的所有 HTML 或 XML 元素,可以用来操作这些元素的内容和特性。
另外还有一些节点类型,分别表示文本内容、注释、文档类型、CDATA 区域和文档片段。
理解 DOM 的关键,就是理解 DOM 对性能的影响。DOM 操作往往是 JavaScript程序中开销最大的部分,而因访问 NodeList 导致的问题为最多。 NodeList 对象都是“动态的”,这就意味着每次访问NodeList 对象,都会运行一次查询。有鉴于此,最好的办法就是尽量减少 DOM 操作。