HTML DOM
·
Yin灏
构造器 | 父级构造器 | Core或HTML | 说明 |
---|---|---|---|
Node | Core | DOM 树上所有的节点都属于 Node | |
Document | Node | Core | Document 对象,主要用于表示 XML 文档项目 |
HTMLDocument | Document | HTML | 即 window.document 或简写 document 所指向的对象 |
Element | Node | Core | 在源文档中,每一个标签都是一个元素 |
HTMLElement | Element | HTML | 这是一个通用性的构造器,所有与 HTML 元素有关的构造器都继承于该对象 |
HTMLBodyElement | HTMLElement | HTML | 用于表示 <body> 标签的元素 |
HTMLLinkElement | HTMLElement | HTML | 代表一个 A 元素 |
其他构造器 | HTMLElement | HTML | 剩下所有 HTML 页面元素 |
CharacterData | Node | Core | 文本处理类的通用性构造器 |
Text | CharacterData | Core | 即插入到标签中的文本节点 |
Comment | CharacterData | Core | 即 <!--HTML注释--> |
Attr | Node | Core | 用于代表各标签中的属性,例如在代码 <p id="closer"></p> 中,属性 id 也是一个 DOM 对象,由 Attr() 负责处理 |
NodeList | Core | 即节点列表,是一个用于存储对象,拥有自身 length 属性的类数组对象 | |
NameNodeMap | Core | 其功能与上一个相同,不同之处在于,该对象中的元素是通过对象名而不是数字索引来访问的 | |
HTMLCollection | Core | 其功能与前两个对象相似,但它是为 HTML 特性量身定制的 |
DOM 节点的访问
- 文档节点
// 控制台输入
console.dir(document);
在 DOM 中,节点类型有 12 种,每种类型分别用一个整数来表示,常用的如下:
- document 的节点类型:9
- 元素的节点类型:1
- 属性的节点类型:2
- 文本的节点类型:3
另外,节点也各自有各自的名称,对于文本节点,其名字就是 #text,document 节点的名字是 #document (document.nodeName)
同时节点也都有各自的节点值,例如,文本节点的值就是它的实际文本,但 document 节点中却不包含任何值 document.nodeValue (null)
- documentElement
documentElement 表示根节点 <html></html>
,
document.documentElement; // <html></html>
document.documentElement.nodeType; // 1 (元素类节点)
对于元素类节点来说,其 nodeName 和 tagName 属性就等于该标签本身的名字
document.documentElement.nodeName; // 'HTML'
document.documentElement.tagName; // 'HTML'
- 子节点
如果要检查一个节点是否含有子节点,可以调用 hasChildNodes() 方法
document.documentElement.hasChildNodes(); // true
HTML 元素有三个子节点 - head、body以及两者之间的空白 (大多数浏览器都会将空白算在内,但不是所有浏览器都如此),我们可以通过该元素的 childNodes 这个类似于数组的集合来访问它们。
document.documentElement.childNodes.length; // 3
document.documentElement.childNodes[0]; // <head>...</head>
document.documentElement.childNodes[1]; // #text
document.documentElement.childNodes[2]; // <body>...</body>
任何节点都可以通过其自身的 parentNode 属性来访问它的父节点
document.documentElement.childNodes[1].parentNode; // <html>...</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>title</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="./css/index.css">
<script defer src="./js/index.js"></script>
</head>
<body>
<p class="opener">first paragraph</p>
<p><em>second</em> paragraph</p>
<p id="closer">final</p>
<!-- and that's about it -->
</body>
</html>
var bd = document.documentElement.childNodes[2];
console.log(bd); // <body>...</body>
console.log(bd.childNodes.length); // 9
/*
NodeList(9) [text, p.opener, text, p, text, p#closer, text, comment, text]
0: text
1: p.opener
2: text
3: p
4: text
5: p#closer
6: text
7: comment
8: text
length: 9
[[Prototype]]: NodeList
*/
- 属性
bd.childNodes[1]; // <p class="opener">first paragraph</p>
// 检查是否存在属性
bd.childNodes[1].hasAttributes(); // true
// 检查有几个属性
bd.childNodes[1].attributes; // NamedNodeMap {0: class, class: class, length: 1}
bd.childNodes[1].attributes.length; // 1
// 获取属性名
bd.childNodes[1].attributes[0].nodeName; // 'class'
// 获取属性值
bd.childNodes[1].attributes[0].nodeValue; // 'opener'
bd.childNodes[1].attributes['class'].nodeValue; // 'opener'
bd.childNodes[1].getAttribute('class'); // 'opener'
- 访问标签中的内容
bd.childNodes[1].nodeName; // 'P'
bd.childNodes[1].textContent; // 'first paragraph'
bd.childNodes[1].innerText; // 'first paragraph'
bd.childNodes[1].innerHTML; // 'first paragraph'
- DOM 访问的快捷方法
document.getElementsByTagName('p').length; // 3
document.getElementsByTagName('p')[0]; // <p class="opener">first paragraph</p>
// 获取元素 id
document.getElementsByTagName('p')[2].id; // 'closer'
// 获取 class 名称
document.getElementsByTagName('p')[0].className; // 'opener'
// 获取页面所有元素
document.getElementsByTagName('*').length
// id
document.getElementById('closer');
还支持其他方法:
- getElementByClassName()
- querySelector()
- querySelectorAll()
- 兄弟节点、body元素及首尾子节点
- nextSibling
- previousSibling
var para = document.getElementById('closer');
console.log(para.nextSibling); // #text
console.log(para.previousSibling); // #text
console.log(para.previousSibling.previousSibling); // <p></p>
console.log(para.previousSibling.previousSibling.previousSibling); // #text
console.log(para.previousSibling.previousSibling.nextSibling.previousSibling); // <p></p>
对于 body 元素来说,下面是一些常用的快捷方式:
document.body; // <body></body>
document.body.nextSibling; // null
document.body.previousSibling; // <head></head>
另外 firstChild / lastChild,
- firstChild 等价于 childNodes[0]
- lastChild 等价于 childNodes[childNodes.length - 1]
document.body.firstChild;
document.body.lastChild;
document.body.lastChild.previousSibling;
document.body.lastChild.previousSibling.nodeValue;
- 遍历 DOM
function walkDOM(n) {
do {
console.log(n)
if (n.hasChildNodes()) {
walkDOM(n.firstChild);
}
} while (n = n.nextSibling);
}
walkDOM(document.documentElement)
DOM 节点的修改
- 修改样式
my.style.border = "1px solid red";
my.style.fontWeight = 'bold';
通过 style 的 cssText 属性,将 CSS 样式当做字符串处理
my.style.cssText; // "border: 1px solid red; font-weight: bold"
// 修改
my.style.cssText += " border-style: dashed"
新建节点
var myp = document.createElement('p');
myp.innerHTML = 'yet another';
myp.style.border = '2px dotted blue';
document.body.appendChild(myp);
纯净DOM
var myp = document.createElement('p');
var myt = document.createTextNode('one more paragraph');
myp.appendChild(myt);
var str = document.createElement('strong');
str.appendChild(document.createTextNode('bold'));
myp.appendChild(str);
document.body.appendChild(myp);
cloneNode()
- true: 深拷贝,包括所有自己点
- false: 浅拷贝,只针对当前节点
insertBefore()
将新元素插入到指定元素的前面
document.body.insertBefore(
document.createTextNode('boo!'),
document.body.firstChild
)
移除节点
要想从 DOM 树汇总移除一个节点,我们可以调用 removeChild()
var myp = document.getElementsByTagName('p')[1];
// 如果稍后还需要用到被移除的节点的话,可以保存该方法的返回值
var removed = document.body.removeChild(myp);
console.log(removed); // <p>...</p>
conosole.log(removed.firstChild); // <em>...</em>
此外,还有一个 replaceChild() 方法,该方法可以在移除一个节点的同时将另一个节点放在该位置。
var p = document.getElementsByTagName('p')[1]; // <p id="closer">final</p>
// 返回被移除节点的引用,<p id="closer">final</p>
var replaced = document.body.replaceChild(removed, p); //
如果我们想将某个子树中的内容一并抹去的话,
document.body.innerHTML = ''; // 最快捷的方式
下面方法用于删除某个指定节点所有子节点的函数:
function removeAll(n) {
while(n.firstChild) {
n.removeChild(n.firstChild)
}
}
removeAll(document.body)
只适用于 HTML 的 DOM 对象
- 访问文档的基本方法
- document.images: 当前页面中所有图片的集合
- document.links: 当前页面中所有A标签的集合
- document.forms: 当前页面中所有表单的集合
/*
<form action="">
<p>姓名</p>
<input type="text" name="username" />
<p>密码</p>
<input type="text" name="password" />
<textarea></textarea>
<select>
<option value="1">1</option>
</select>
</form>
*/
console.log(document.forms[0].elements); // HTMLFormControlsCollection(4) [input, input, textarea, select]
console.log(document.forms[0].elements[0].value);
document.forms[0].elements[0].value = 'first input';
document.forms[0].elements[0].disabled = true;
// 如果 form 本身或 form 的元素拥有 name 属性的话,也可以通过 name 名来访问
document.forms[0].elements['username'];
document.forms[0].elements.username;