1. DOM节点
1.1. 根据W3C html DOM标准, html文档中的所有事物都是节点:
- 整个文档是文档节点。
- 每个html元素是元素节点。
- html元素内的文本是文本节点。
- 每个html属性是属性节点。
- 所有注释是注释节点。
2. 节点关系
2.1. 节点树中的节点彼此之间有一定的等级关系。
- 术语, 父(parent)、子(child)和同胞(sibling)用于描述这些关系。
- 在节点树中, 顶端节点被称为根(根节点)。
- 每个节点都有父节点, 除了根(根节点没有父节点)。
- 节点能够拥有一定数量的子。
- 同胞(兄弟或姐妹)指的是拥有相同父的节点。
2.2. 实例
<html>
<head>
<title>DOM 教程</title>
</head>
<body>
<h1>DOM 第一课</h1>
<p>Hello world!</p>
</body>
</html>
2.3. 实例节点关系
2.4. 从以上的html中您能读到以下信息:
<html>是根节点
<html>没有父
<html>是<head>和<body>的父
<head>是<html>的第一个子
<body>是<html>的最后一个子
同时:
<head>有一个子: <title>
<title>有一个子(文本节点): "DOM 教程"
<body>有两个子: <h1>和<p>
<h1>有一个子: "DOM 第一课"
<p>有一个子: "Hello world!"
<h1>和<p>是同胞
3. 在节点之间导航
3.1. 通过JavaScript, 您可以使用以下节点属性在节点之间导航:
- parentNode
- children
- childNodes[nodenumber]
- firstChild
- lastChild
- nextSibling
- nextElementSibling
- previousSibling
- previousElementSibling
4. parentNode属性
4.1. parentNode属性可返回某节点的父节点。如果指定的节点没有父节点则返回null。
4.2. 语法
node.parentNode
5. children属性
5.1. children属性返回元素的子元素的集合, 是一个HTMLCollection对象。
5.2. 根据子元素在元素中出现的先后顺序进行排序。使用HTMLCollection对象的length属性获取子元素的数量, 然后使用序列号(index, 起始值为0)访问每个子元素。
5.3. 语法
element.children
6. childNodes属性
6.1. childNodes属性返回包含被选节点的子节点的NodeList。
6.2. 如果选定的节点没有子节点, 则该属性返回不包含节点的NodeList。如需循环子节点列表, 使用nextSibling属性, 要比使用父对象的childNodes列表效率更高。
6.3. 语法
element.childNodes
6.4. children属性与childNodes属性的差别:
6.4.1. childNodes属性返回所有的节点, 包括文本节点、注释节点。
6.4.2. children属性只返回元素节点。
7. firstChild属性
7.1. firstChild属性返回被选节点的第一个子节点对象。如果选定的节点没有子节点, 则该属性返回NULL。
7.2. firstChild属性包括文本节点、注释节点。
7.3. 语法
node.firstChild
8. lastChild属性
8.1. lastChild属性可返回文档的最后一个子节点对象。
8.2. lastChild属性包括文本节点、注释节点。
8.3. 语法
node.lastChild
9. nextSibling属性
9.1. nextSibling属性可返回某个元素之后紧跟的节点(处于同一树层级中)。
9.2. 返回节点对象。如果元素紧跟后面没有节点则返回null。
9.3. 语法
node.nextSibling
10. nextElementSibling属性
10.1. nextElementSibling属性返回指定元素之后的下一个兄弟元素(相同节点树层中的下一个元素节点)。
10.2. 返回节点对象。如果元素紧跟后面没有节点则返回null。
10.3. 语法
node.nextElementSibling
10.4. nextSibling属性与nextElementSibling属性的差别:
10.4.1. nextSibling属性返回元素节点之后的兄弟节点(包括文本节点、注释节点)。
10.4.2. nextElementSibling属性只返回元素节点之后的兄弟元素节点(不包括文本节点、注释节点)。
11. previousSibling属性
11.1. previousSibling属性可返回某节点之前紧跟的节点(处于同一树层级)。
11.2. 返回节点对象。如果元素紧跟后面没有节点则返回null。
11.3. 语法
node.previousSibling
12. previousElementSibling属性
12.1. previousElementSibling属性返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
12.2. 返回节点对象。如果元素紧跟后面没有节点则返回null。
12.3. 语法
node.previousElementSibling
12.4. previousSibling属性与previousElementSibling属性的差别:
12.4.1. previousSibling属性返回元素节点之前的兄弟节点(包括文本节点、注释节点)。
12.4.2. previousElementSibling属性只返回元素节点之前的兄弟元素节点(不包括文本节点、注释节点)。
13. hasChildNodes()方法
13.1. hasChildNodes()方法可在某节点用于任何子节点时返回true, 否则返回false。。
13.2. 语法
node.hasChildNodes()
14. nodeValue属性
14.1. nodeValue属性规定节点的值。
- 元素节点的nodeValue是null
- 文本节点的nodeValue是文本
- 属性节点的nodeValue是undefined
15. 节点值
15.1. DOM处理中的一种常见错误是认为元素节点中包含文本。
15.2. 实例:
// <p>元素节点不包含文本。
// "DOM 教程"是另一个节点, <p>元素节点的子节点, 是文本节点
<p id="demo">DOM 教程</p>
15.3. 文本节点的值能够通过节点的innerHTML属性进行访问:
var myTitle = document.getElementById("demo").innerHTML;
15.4. 访问innerHTML属性等同于访问首个子节点的nodeValue:
var myTitle = document.getElementById("demo").firstChild.nodeValue;
// 也可以这样访问第一个子节点:
var myTitle = document.getElementById("demo").childNodes[0].nodeValue;
16. nodeName属性
16.1. nodeName属性规定节点的名称。
- nodeName是只读的
- 元素节点的nodeName等同于标签名
- 属性节点的nodeName是undefined
- 文本节点的nodeName总是#text
- 文档节点的nodeName总是#document
17. nodeType属性
17.1. nodeType属性返回节点的类型。nodeType是只读的。
17.2. 最重要的nodeType属性是:
18. 例子
18.1. 代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>DOM导航</title>
</head>
<body>
<div id="myDiv" style="border: solid 1px; width: 600px;height: 240px;">
<ul id="myUl">
<li>parentNode</li>
<li>children</li>
<li>childNodes[nodenumber]</li>
<li>firstChild</li>
<li>lastChild</li>
<li>nextSibling</li>
<li>nextElementSibling</li>
<li>previousSibling</li>
<li>previousElementSibling</li>
<li>hasChildNodes</li>
</ul>
</div>
<script type="text/javascript">
var myDiv = document.getElementById("myDiv");
var myUl = document.getElementById("myUl");
var firstLi = document.querySelector("li:first-child");
var lastLi = document.querySelector("li:last-child");
document.write("<br />div的父元素节点名称: " + myDiv.parentNode.nodeName + "<hr />");
var childrens = Array.prototype.slice.call(myUl.children);
document.write("children: " + myUl.children);
for(let idx in childrens){
document.write("<br />ul子节点名称: " + childrens[idx].nodeName);
}
var childNodes = Array.prototype.slice.call(myUl.childNodes);
document.write("<hr />childNodes: " + myUl.childNodes);
for(let idx in childNodes){
document.write("<br />ul子节点名称: " + childNodes[idx].nodeName);
}
document.write("<hr />firstChild: " + myDiv.firstChild);
document.write("<hr />lastChild: " + myDiv.lastChild);
document.write("<hr />nextSibling: " + firstLi.nextSibling);
var nes = firstLi.nextElementSibling;
document.write("<hr />nextElementSibling: " + nes);
document.write("<br />" + firstLi.innerHTML);
while(nes){
document.write("<br />" + nes.innerHTML);
nes = nes.nextElementSibling;
}
document.write("<hr />previousSibling: " + lastLi.previousSibling);
var pes = lastLi.previousElementSibling;
document.write("<hr />previousElementSibling: " + pes);
document.write("<br />" + lastLi.innerHTML);
while(pes){
document.write("<br />" + pes.innerHTML);
pes = pes.previousElementSibling;
}
document.write("<hr />最后一个li是否有字节点: " + lastLi.hasChildNodes());
</script>
</body>
</html>
18.2. 效果图
19. 例子
19.1. 代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>nodeValue、nodeName、nodeType属性</title>
</head>
<body>
<a id="demo" href="http://www.baidu.com">DOM 教程</a><br />
<!-- 这是注释 -->
<script type="text/javascript">
var demo = document.getElementById("demo");
document.write('元素节点的nodeName是: ' + demo.nodeName + '<br />');
document.write('文本节点的nodeName是: ' + demo.firstChild.nodeName + '<br />');
document.write('属性节点的nodeName是: ' + demo.href.nodeName + '<br />');
document.write('文档节点的nodeName是: ' + document.nodeName + '<br /><br />');
document.write('元素节点的nodeType是: ' + demo.nodeType + '<br />');
document.write('文本节点的nodeType是: ' + demo.firstChild.nodeType + '<br />');
document.write('属性节点的nodeType是: ' + demo.href.nodeType + '<br />');
document.write('注释节点的nodeType是: ' + document.body.childNodes[4].nodeType + '<br />');
document.write('文档节点的nodeType是: ' + document.nodeType + '<br />');
document.write('文档声明的nodeType是: ' + document.doctype.nodeType + '<br /><br />');
document.write('使用innerHTML访问文本值: ' + demo.innerHTML + '<br />');
document.write('使用nodeValue访问文本值: ' + demo.firstChild.nodeValue + '<br />');
demo.firstChild.nodeValue = '百度一下';
document.write('使用索引+nodeValue访问文本值: ' + demo.childNodes[0].nodeValue + '<br />');
document.write('元素节点的nodeValue是: ' + demo.nodeValue + '<br />');
document.write('属性节点的nodeValue是: ' + demo.href.nodeValue);
</script>
</body>
</html>
19.2. 效果图