HTML文档可以看成由各种 DOM 节点组成的文档树,例如:整篇文档是一个文档节点;第个标签都是一个元素节点;文本内容可以看成文本节点;标签属性是属性节点,甚至注释也是注释节点。
nodeType
元素节点的类型可以通过node.nodeType访问,例如:
document.nodeType # 9
主要的节点类型如下所示:
Element Type | Node Type |
---|---|
Element | 1 |
Attribute | 2 |
Text | 3 |
Comment | 8 |
Document | 9 |
除此之外,节点还有一些其它属性,例如nodeName、nodeValue、tagName等。
nodeName
其中nodeName是最有用的属性,它包含的是节点的名称。元素节点的名称是标签名,属性节点的名称是属性名,文本节点的名称是#text,而文档节点的名称是#document。需要注意的是,nodeName包含的节点名字总是大写的。节点的另外一个属性tagName也包含了元素节点的标签名,但它对任何其它类型的节点都不可用,因此实用价值不大。
nodeValue
对于文本节点,nodeValue包含实际的文本内容;对于属性节点,它包含属性的值。而对于元素节点和文档结点则不可用。
寻找 DOM 元素
要开始DOM编程,首先需要找到你所需要进行操作的元素。一般情况下有两种方法可以使用:
- 通过getElementById或者getElementsByTagName函数。
- 通过元素的parentNode及其它类似的属性。
其中,前者可以称为长途搜索,后者相对前者可以称为短途搜索。前者可以不管文档的结构而搜索所需要的节点或者节点列表,而后者则是从一个节点至另外一个节点的短距离搜索,它需要了解目标节点是源节点的爷节点还是兄弟节点等。
长途搜索
长途搜索的几个函数如下所示:
document.getElementById() element.getElementsByTagName() element.getElementsByName() element.getElementsByClassName()
其中,第一个只能用于document节点,在整个文档中搜索指定id的节点并返回。后三个可以用于任何HTML元素,分别搜索指定标签名、name属性、class属性的节点并返回一个节点列表。
短途搜索
节点拥有5个属性(parentNode、firstChild、lastChild、nextSibling、previousSibling)和两个节点列表(childNodes[]和children[])来允许你进行短途搜索。当然,并不是每个节点都拥有以上所有的属性,例如文档节点是整个文档的根节点,因此这没有父节点;而文本节点则不能拥有子节点。
nextSibling、previousSibline这对属性分别查找节点的前后兄弟节点,该节点有可能是文本节点。如果要查找非文本兄弟结点,可以使用nextElementSibling和previousElementSibling属性。
childeNodes[]和children[]之间的区别与上面的nextSibling和nextElementSibling的区别相同,前者返回所有子节点,而后者仅返回所有类型为元素节点的子节点。
修改 DOM 文档树
有4个函数来修改文档树,分别是appendChild、insertBefore、removeChild和replaceChild,其中前两个最常用,replaceChild用得相对来说比较少。
一般规则
所有这4个函数返回的都是它们所操作的节点的引用,并且都定义在你想要操作的节点的父节点上。例如,你想要删除节点x,需要这样做:
x.parentNode.removeChild(x)
appendChild
appendChild函数可以添加一个节点并使它成为某个元素的最后一个节点。如果该节点已经存在于文档中,它会从当前位置被移除。该节点的子节点也被一起移动到新位置。
insertBefore
insertBefore函数可以将一个节点插入到其它节点前面,同appendChild一样如果该节点已经存在于文档中,它会从当前位置被移除。该节点的子节点也被一起移动到新位置。
removeChild
removeChild函数可以从文档中移除一个节点以及它的子节点。
replaceChild
replaceChild函数可以把文档中的一个节点替换成另外一个节点。其它同appendChild和insertBefore函数一样。
移除所有的子节点
有时候可能需要将一个节点的所有子节点都移除,有两种方法可以完成这个任务,第一种是使用removeChild函数:
while (x.childNodes[0]) x.removeChild(x.childNodes[0])
通过简单的while循环,只要仍然存在第一个子节点,就将它从x中删除,直到x没有子节点为止。V
第二种方法就更简单了,只要设置元素的innerHTML属性为空就可以了:
x.innerHTML=""
创建和克隆元素
你可以创建自己的元素和文本节点,并把它们添加到文档树中。也允许你克隆已有的元素,以便你能方便地复制文档的某一个部分以备它用。
createElement和createTextNode
createElement和createTextNode函数正如它们名字所说的那样,分别是创建一个元素节点和文本节点:
var x = document.createElement("p"); var y = document.createTextNode("This is a created element");
x指向新创建的元素节点, y指向新创建的文本节点。目前为止,这些节点并没有添加到文档树中,因此它们还不能正常地呈现在页面上。所需要的就是使用appendChild或者insertBefore函数将它们添加到文档树的某个位置,例如:
x.appendChild(y); document.body.appendChild(x);
现在,y被添加到x节点并作为它的文本子节点,而x被添加到document.body节点的最后一个位置。在使用createTextNode函数的时候需要注意的是,它并不能创建©等HTML实体,而是会原封不动的创建文本节点,遇到这种情况可以考虑使用innerHTML。
cloneNode
cloneNode函数可以克隆一个节点,通过指定参数为true或者false,它可以选择复制或者不复制它的所有子节点。但是一般情况下,参数都会选择true。遗憾的是,cloneNode函数不会复制事件处理程序,因此当你克隆一个节点之后,需要重新定义事件处理程序。
innerHTML
关于innerHTML和其它方法的一个速度比较在这里:Benchmark - W3C DOM vs. innerHTML