一,DOM 的定义
DOM(Document Object Model,文档对象模型),是一种API,其作用为在程序中使用HTML 文档以及XML 文档。在DOM 中,HTML 文档与 XML 文档会以树形对象集合的形式被使用。这一树形结构称为 DOM 树。
DOM 树中的一个个对象被称为节点。节点之间形成了一个树形结构,树中的某个节点可能会引用另 外一个节点。根据引用关系,分别有父节点、子节点、兄弟节点、祖先节点、子孙节点等类型。
DOM 的表述方式:
- 接口名 . 方法名 ()
- 接口名 . 属性名
二,DOM 的基础
- 标签是一种用于标记的字符串,其作用为对文档的结构进行指定。
- 元素和节点之间略有一些继承关系,其中节点是父类概 念。节点具有 nodeType 这一属性,如果其值为 ELEMENT_NODE(1),该节点则是一个元素。
节点 | 节点类型常量 | 节点类型的值 | 接口 |
---|---|---|---|
元素节点 | ELEMENT_NODE | 1 | Element |
属性节点 | ATTRIBUTE_NODE | 2 | Attr |
文本节点 | TEXT_NODE | 3 | Text |
注释节点 | COMMENT_NODE | 8 | Comment |
文档节点 | DOCUMENT_NODE | 9 | Document |
Document 对象是DOM 树结构中的根节点。虽然这是一个根节点,在HTML 文档中却不用书写其对 应的标签。可以通过JavaScript 中的document 这一全局变量来访问Document 对象。准确地说,document 是 window 对象中的一个属性。不过,由于window 对象是一个全局对象,因此在对其属性进行访问时可以 将 window. 省略不写。,window 对象并没有包含于DOM 树结构之中。
三,节点的选择
通过 ID 检索
Document.getElementById() 方法。ID 在 DOM 树中必须是唯一的,大部分的浏览器都采用了返回第一个找到的元素的方式。
通过标签名检索
Element.getElementsByTagName() 方法。需要注意的是,getElementsByTagName() 所能取得的对象是一个NodeList 对象,而不是单纯 的 Node 对象的数组。而NodeList 对象的一大特征就是它是一个Live 对象。
<div id="foo">
<span>first</span>
<span>second</span>
</div>
<script>
var elems = document.getElementsByTagName('span');
alert(elems.length); // => 2
var newSpan = document.createElement('span');
newSpan.appendChild(document.createTextNode('third'));
var foo = document.getElementById('foo');
foo.appendChild(newSpan);
alert(elems.length); // => 3
</script>
HTMLCollection | 说明 |
---|---|
document.images | 文档中所有的 img 元素 |
document.applets | 文档中所有的 Java Applet 对象 |
document.links | 文档中所有的链接元素(那些被指定了 href 属性的元素) |
document.forms | 文档中所有的 form 元素 |
document.anchors | 文档中所有的锚元素(那些被指定了 name 属性的元素) |
form.elements | 表单中所有的 input 元素 |
map.areas | 图像映射中所有的 area 元素 |
table.rows | 表格中所有的 tr 元素 |
table.tBodies | 表格中所有的 tbody 元素 |
tableSection.rows | 表格区段(thead 元素、tfoot 元素)中所有的 tr 元素 |
row.cells | 表格的一行中所有的 td 元素与 th 元素 |
通过名称检索
Document.getElementsByName() 方法,可以将name 属性的值作为限定条件来获取属性。
通过类名检索
Element.getElementsByClassName() 方法,就可以获取指定类名的元素。其中的类名可以指定多个值。如果想要指定多个类名,则需要使用空白符作为分隔字符串。也就是 类似于 'classA classB' 的形式。
父节点、子节点、兄弟节点
1. 一些用于引用相关节点的属性
- parentNode 父节点
- childNodes 子节点列表,通过childNodes 获取的对象都是NodeList 对象
- firstChild 第一个子节点
- lastChild 最后一个子节点
- nextSibling 下一个兄弟节点
- previousSibling 上一个兄弟节点
2. 一些用于引用相关元素的属性
- children 子元素节点列表
- firstElementChild 第一个子元素
- lastElementChild 最后一个子元素
- nextElementSibling 下一个元素
- previousElementSibling 上一个元素
- childElementCount 子元素的数量
XPath
XPath 的使用示例
<script>
var result = document.evaluate(
// id 为 main 的 div / 包含了值为 content 的 class 的 p 元素中的第三个 /href 值的起始部分 为 http://example.com/ 的 a 元素
'//div[@id="main"]/p[contains(@class, "content")][3]/a[starts-with(@href, "http://example.com/")]',
document,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
alert(result.snapshotLength); // => 1
var elem = result.snapshotItem(0);
alert(elem.innerHTML); // => 4th link
</script>
Document.evaluate() 方法 将会接收 5个参数。
第 1 个参数是用于求值的 XPath 表达式的字符串。
第 2 个参数用于指定文档中的节点 。
第 3 个参数可以指定用于返回URI 命名空间的函数。
第 4 个参数指定了返回求值结果时所要使用的对象类型。
第 5 个参数用于指定一个已有的XPathResult 对象。
Selector API
通过querySelectorAll() 则可以获取所有符合条件的元素。
通过querySelector() 将只会返回第一 个与条件相符的元素。
Selectors API 的使用示例
var a = document.querySelector('#foo');
var b = document.getElementById('foo');
alert(a === b); // => true
var c = document.querySelectorAll('div');
var d = document.getElementsByTagName('div');
alert(c[0] === d[0]); // => true
四,节点的创建与新增
可以通过Document.createElement() 方法或Document.createTextNode() 方法来创建节点。还可以通过 Document.createComment()方法来创建一个注释。
如果要将节点新增为某一节点的最后一个子元素,则可以使用Node.appendChild() 方法。而如果要 将节点插入至某一元素所在的位置,则需要使用 Node.insertBefore()方法。
var elem = document.createElement('div');// 创建一个 div 元素
var text = document.createTextNode('This is a new div element.');// 创建一个文本节点
document.body.appendChild(elem);// 将所创建的 div 元素添加至 body 之下
elem.appendChile(text);// 将文本节点添加至所创建的 div 元素中
var comment = document.createComment('this is comment'); // 创建一个注释节点
document.body.insertBefore(comment, elem); // 在 elem 之前插入该注释节点
五,节点的内容更改
通过Node. replaceChild()方法替换节点。
var newNode = document.createElement('div');
var oldNode = document.getElementById('foo');
var parentNode = oldNode.parentNode;
parentNode.replaceChild(newNode, oldNode);
六,节点的删除
通过 Node.removeChild()方法来删除节点。
var elem = document.getElementById('foo');
elem.parentNode.removeChild(elem);
七,innerHTML/textContent
var elem = document.getElementById('foo');
elem.innerHTML = '<div>This is a new div element.</div>';
var elem = document.getElementById('foo');
elem.textContent = '<div>Is this a new div element?</div>';
// => 不会创建 div 元素。在浏览器中将会直接显示该字符串
八,使用 DocumentFragment
var fragment = document.createDocumentFragment();
for (var i = 0; i < 10; i++) {
var child = document.createElement('div');
// 向 DocumentFragment 添加子元素
fragment.appendChild(child);
}
// 向父元素中添加 DocumentFragment
// 虽然添加的是 DocumentFragment,但实际上添加的仅仅是 DocumentFragment 的子元素
document.getElementById('parent').appendChild(fragment);