DOM(文档对象模型)
DOM可以将任何HTML或XML文档映射成一个多层节点的树形结构。节点有不同的类型,每种类型分别表示不同的信息或标记。每个节点都有各自的特点、数据和方法,也与其它的节点存在某种关系。节点之间构成了层次,页面中的所有节点构成了以某个特定节点为根节点的树形结构。
简单点说,就是DOM将HTML文档映射为带有属性、元素和文本的树形结构。
以下面的HTML为例:
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>节点类型</tilte>
</head>
<body>
<h2>JavaScript DOM</h2>
<p class="p1">hello JavaScript!!</p>
<ul>
<li>JavaScript</li>
<li>BOM</li>
<li>DOM</li>
</ul>
<script>
</script>
</body>
</html>
DOM将其映射为树形结构的形式为:
以上的节点有:
1、元素节点,如:<html>、<p>、<body>等都属于元素节点。
2、属性节点,如:p元素的class属性。
3、文本节点,如:<li>元素中的JavaScript、BOM、DOM等文本均属于文本节点。
在页面中<html>元素被称为文档元素,一个页面也只有一个文档元素即<html>元素,文档元素包含了所有的文档节点,每个标记通过节点来表示,HTML元素通过元素节点表示 ,特性通过特性节点表示,注释通过注释节点表示,文档类型通过文档类型节点表示。
Document类型
- nodeType的值为9
- nodeName的值为#document
- nodeValue的值为null
- parentNode的值为null
- 它的子节点有可能是:DocumentType(也就是!doctype html 最多一个)、Element(也就是<html>文档元素 最多一个)。
访问子节点的快捷方式
documentElement
var html = document.documentElement; //取得对<html>的引用
console.log(html); //<htmll>...</html>
//Document节点的子节点(DocumentType Element)
console.log(document.childNodes[0]); //<!DOCTYPE html>
console.log(document.childNodes[1]); //<htmll>...</html>
console.log(document.childNodes[2]); //undefined
在一个文档中,<!doctype html>和<html>是Document节点(documentElment 文档节点)的子节点。
document.body属性
var body = document.body; //取得对<html>的引用
console.log(body); //<htmll>...</html>
//body节点的子节点,是body下的所有元素节点
console.log(body.childNodes[0]); //#text 文本节点
console.log(body.childNodes[1]); // <p></p>
console.log(body.childNodes[2]); // #text
console.log(body.childNodes[3]); // <script>...</script>
DocumentType
var doctype = document.doctype;
console.log(doctype); //<!DOCTYPE html>
文档信息
对文档信息的访问。
- document.title,表示对文档标题的访问
- document.URL,表示对文档的URL的访问
- document.charset,表示对文档字符编码形式的访问
特殊集合
- document.anchors,返回包含所有带有name属性的<a>元素
- document.links,返回包含所有带有href属性的<a>元素
- document.images,返回文档中所有的<img>元素
- document.forms,返回文档中所有的<form>元素
文档的写入方法
- document.write(),表示写入要输出的文本,并输出到文档中。此方法会覆盖原内容。
- document.writeln(),与以上方法相同,不过这个方法会在末尾添加一个"/n"换行符。
- document.open(),打开网页的输出流。
- document.close(),关闭网页的输出流。
查找元素
通过什么样的方式来查找页面中的元素,常见的是通过ID、元素标签名、元素的类名、元素的name属性查找。
getElementById()
该属性通过ID来获取元素。通过获取元素,可以对其进行赋值、添加样式、隐藏等操作。
注意:因为ID是唯一的,所以查找到的元素也是唯一的,返回的是一个元素。
<body>
<h2 id="con">I love JavaScript!</h2>
<p id="p2">hello JavaScript!!</p>
<script>
var con = document.getElementById("con"); //通过ID获取元素
con.style.color = "red"; //将文字颜色设置高红色
con.style.backgroundColor = "#ccc"; //将文字背景色设置为灰色
</script>
</body>
getElementsByName()
通过name属性获取元素,返回带有指定名称的元素节点的集合。
注:name属性不是唯一的,可能有多个元素有共同的name属性名,所以可能获取的元素有多个,可以看作是一个数组。有length属性可以进行访问。
<body>
<input name="myt" type="text" value="1">
<input name="myt" type="text" value="2">
<input name="myt" type="text" value="3">
<input name="myt" type="text" value="4">
<input name="myt" type="text" value="5">
<input name="myt" type="text" value="6">
<script>
var con = document.getElementsByName("myt"); //通过name获取元素,元素可以有多
个。
console.log(con.length); //6 表示有6个name为myt的元素
</script>
返回的顺序是它们在文档中的顺序。
getElementsByTagName()
通过标签名(元素名称)获取元素。返回带有指定标签名的节点对象的集合,返回的顺序是它们在文档中的顺序。可以通过length属性访问。
注:该方法返回的看作是一个数组。
<body>
<input name="myt" type="text" value="1">
<input name="myt" type="text" value="2">
<input name="myt" type="text" value="3">
<input name="myt" type="text" value="4">
<input name="myt" type="text" value="5">
<input name="myt" type="text" value="6">
<script>
var con = document.getElementsByTagName("input"); //通过标签名input获取节点对象,对象可以有多个。
console.log(con.length); //6 表示有6个标签名为input的节点对象。
</script>
getElementsByClaseName()
通过元素的类名来查找元素,返回的是一个nodeList类型,类似数组一样,可以通过argument、length属性访问。
Element类型
该类型表示HTML元素节点的访问,可以访问元素的标签名、子节点、属性。它的特点:
- nodeType的值为1
- nodeName的值为它的标签名及元素名
- nodeValue的值为null
- parentNode是Document或Element(其它元素节点)
- 它的子节点可能是:Element、Text。
访问元素节点的方式
var p1 = document.getElementById("p1");
console.log(p1); //<p>...</p>
console.log(p1.nodeName); //p
console.log(p1.tagName); //p
取得属性(特性)
getAttribute()
通过 元素节点的 属性名 获取 属性的值。
格式:elementNode.getAttribute("属性名");
<body>
<ul>
<li title="t1">第一个li</li>
<li>第二个li</li>
<li title="t3">第三个li</li>
<li title="t4">第四个li</li>
</ul>
<script>
var con = document.getElementsByTagName("li"); //通过标签名获取节点对象。
for (var i = 0; i < con.length; i++) {
var text = con[i].getAttribute("title"); //通过元素节点的属性名称获取属性的值。
if (text != null) {
console.log(text); //t1 t3 t4
}
}
</script>
</body>
设置属性(特性)
setAttribute()
该方法增加一个 指定名称和值 的新属性,或把现有的属性设定为 指定的值。
格式:elementNode.setAttribute("属性名", "属性值")
注:把指定的属性设定为指定的值,如果不存在具有指定的属性,则该方法创建一个。
<body>
<li id="l" title="li1">1</li>
<p id="2"></p>
<script>
var con = document.getElementById("l");
var cos = document.getElementById("2");
con.setAttribute("title", "WEB前端技术"); //把现有的属性设定为指定的值
cos.setAttribute("name", "pad"); //对于没有的属性,则新创建。
console.log(con.getAttribute("title")); //WEB前端技术
console.log(cos.getAttribute("name")); //pad
</script>
</body>
对于li节点对象,将其现有的属性title的值"li1"设定为指定的值"WEB前端技术"。而对于p节点对象,该节点原本没有属性name,通过setAttribute()方法,给其新创建了一个属性name并赋值"pad"。
removeAttribute()
该方法删除元素的属性。
<p id="p1" name="p"></p>
<script>
var p1 = document.getElementById("p1");
p1.removeAttribute("name"); //删除p元素的name属性
var att = p1.getAttribute("name");
console.log(att); // null
</script>
创建新元素节点(document.createElement)
格式:document.createElement("标签名");
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1"><li id="a">JavaScript</li><li id="b">jquery</li><li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//找到JavaScript所在
var node = con.firstChild; //找到ul的第一个子节点
//先创建一个新节点元素
var newNode = document.createElement("li");
newNode.innerHTML = "css";
con.replaceChild(newNode, node); //用新创建的节点去替换JavaScript所在的节点。
</script>
</body>
</html>
先创建一个节点元素,再用其将JavaScript所在节点替换掉。
Node类型
节点属性
在DOM中,每个节点都是一个对象,节点有三个重要的属性:
1、nodeName:节点名称
2、nodeValue:节点的值
3、nodeType:节点的类型
nodeName:节点名称,只是可读的。
1、元素节点的nodeName与标签名相同
2、属性节点的nodeName与属性名相同
3、文本节点的nodeName永远是#text
4、文档节点的nodeName永远是#document
nodeValu:节点的值
1、元素节点的nodeValue是undefined或null
2、文本节点的nodeValue是文本自身
3、属性节点的nodeValue是属性的值
nodeType:节点的类型
1、元素节点的nodeType是 1
2、属性节点的nodeType是 2
3、文本节点的nodeType是 3
4、注释节点的nodeType是 8
5、文档节点的nodeType是 9
<body>
<ul>
<li>javascript</li>
<li>HTML/CSS</li>
<li>jQuery</li>
</ul>
<script type="text/javascript">
var con = document.getElementsByTagName("li");
for(var i=0; i<con.length; i++){
var nodeName = con[i].nodeName;
var nodeValue = con[i].nodeValue;
var nodeType = con[i].nodeType;
document.write(nodeName + "<br>");
document.write(nodeValue + "<br>");
document.write(nodeType + "<br>");
}
</script>
</body>
li元素是元素节点,所有元素节点的nodeName是标签名li,元素节点的nodeValue是undefined或null,元素节点的nodeType是 1。
节点关系
childNodes
访问选定元素节点下的所有子节点的 列表,返回的值可以看作是一个数组,具有length属性。
格式:elementNode.childNodes
注意:元素节点之间的空白符 被默认为 文本节点。
<body>
<div>
javascript
<p>javascript</p>
<div>jQuery</div>
<h5>PHP</h5>
</div>
<script>
var arr = document.getElementsByTagName("div")[0].childNodes; //获取第一个div下的所有子节点。
//遍历所有子节点
for (var i = 0; i < arr.length; i++) {
document.write("节点的名称:" + arr[i].nodeName + "<br>");
document.write("节点的值:" + arr[i].nodeValue + "<br>");
document.write("节点的类型:" + arr[i].nodeType + "<br>");
}
console.log(arr.length); //对于除IE外,其它主浏览器显示的子节点为7个
</script>
</body>
IE下显示的子节点只有3个,而其它主浏览器显示的子节点有7个,因为其它主浏览器把元素节点之间的空白默认为文本节点。
也就是说:
<div>
javascript 文本节点
<p>javascript</p> 文本节点
<div>jQuery</div> 文本节点
<h5>PHP</h5> 文本节点
</div>
这样就有4个文本节点,再加上3个元素节点,就是7个子节点。
firstChild 和lastChild
分别为返回 某节点下的第一个子节点 和返回 某节点下的最后一个子节点。如果某节点没有子节点则返回null。
格式:node.firstChild 和 node.lastChild
<body>
<div id="con"><p>javascript</p><div>jQuery</div><h5>PHP</h5></div>
<script>
var x=document.getElementById("con"); //首先获取第一个div
document.write(x.firstChild.nodeName); //获取第一个div下的第一个子节点的节点名称
document.write(x.lastChild.nodeName); //获取第一个div下的最后一个子节点的节点名称
</script>
</body>
firstChild与elementNode.childNodes[0]效果一样,lastChild与elementNode.childNodes[elementNode.childNodes.length -1]效果一样。
parentNode
获取指定节点的父节点
格式:elementNode.parentNode
注意:父节点只能有一个。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>无标题文档</title>
</head>
<body>
<div>
javascript
<p id="p1">javascript</p>
<div>jQuery</div>
<h5>PHP</h5> <!-- 这里的文本节点 -->
</div>
<script>
var con = document.getElementById("p1"); //根据获取p元素节点
var f = con.parentNode; //接着获取其父节点
var n = f.lastChild; //最后获取父节点的最后一个子节点,即文本节点
console.log(n.nodeName); //#text
</script>
</body>
</html>
根据获取p元素节点来运用父节点知识,最后获取h5与</div>之间的文本节点。
操作节点
访问兄弟节点
兄弟节点:两个紧跟着的节点。
nextSibling:访问节点的下一个紧跟着的节点。
格式:nodeObject.nextSibling
perviousSibling:访问节点的上一个紧跟着的节点。
格式:nodeObject.perviousSibling
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1">
<li id="a">JavaScript</li>
<li id="b">jquery</li>
<li id="c">html</li>
</ul>
<ul id="u2">
<li id="d">css3</li>
<li id="e">php</li>
<li id="f">java</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementsByTagName("li")[0]; //通过标签名找到JavaScript所在的元素节点。
document.write(con.nodeName);
document.write("=");
document.write(con.innerHTML);
//使用nextSibling找到节点的下一个兄弟节点,并判断其是否是元素节点。
function get_nextSibling (n) {
var x = n.nextSibling;
//如果不是元素节点,继续向下查找。利用while语句继续访问下一个兄弟节点。
while (x && x.nodeType != 1) {
x = x.nextSibling;
}
return x; //返回此兄弟节点。
}
var y = get_nextSibling(con);
//判断是否是空节点,如果是空节点,表示已经是最后一个节点了,最后一个节点没有nextSibling。
if (y != null) {
document.write("<br>nextSibling:");
document.write(y.nodeName);
document.write("=");
document.write(y.innerHTML);
} else {
document.write("已经最后一个节点了。");
}
</script>
</body>
</html>
上述例子是通过nextSibling访问JavaScript后面紧跟着的jquery。
效果如下:
插入节点appendChild()
在指定节点的 最后一个子节点列表后面添加一个节点。
格式:nodeObject.appendChild(newNode)
注:是将已经创建成的节点插入到指定节点的最后一个子节点列表后面。
其中,nodeObject表示newNode的父节点。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1">
<li id="a">JavaScript</li>
<li id="b">jquery</li>
<li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//先创建这个新节点
var newNode = document.createElement("li"); //添加一个名的li的元素。
/*var newText = document.createTextNode("css"); //添加一个文本节点。
newNode.appendChild(newText); */
newNode.innerHTML = "css";
con.appendChild(newNode); //将创建好的新节点插入ul的最后一个子节点列表之后。
</script>
</body>
</html>
上述例子是为ul添加一个新项css,第一步就是找到指定的节点ul,第二步就是创建这个新的节点,创建的方法有两种,一是添加一个新的元素li,为其添加文本节点。二是直接用innerTHML添加文本内容。最后一步用appendChild将新创建的节点插入到子节点列表之后。
insertBefore()
在已有的子节点前面添加一个新节点。
格式:nodeObject.insetBefore(newNode,node)
其中,newNode为要插入的新节点。node为已有的子节点,在此节点之前添加新节点。nodeObject表示node的父节点。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1"><li id="a">JavaScript</li><li id="b">jquery</li><li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//找到JavaScript所在
var node = con.firstChild; //找到ul的第一个子节点
//先创建这个新节点
var newNode = document.createElement("li"); //添加一个名的li的元素。
/*var newText = document.createTextNode("css"); //添加一个文本节点。
newNode.appendChild(newText); */
newNode.innerHTML = "css";
//插入节点
con.insertBefore(newNode, node); //将新节点插入到指定节点之前。
</script>
</body>
</html>
在ul节点的第一个子节点前面添加一个新节点。
removeChild()
删除子节点列表中的某个节点,如果删除成功,则返回被删除的节点,如果失败,则返回null。
格式:nodeObject.removeChild(node)
其中,nodeObject表示node的父节点,node表示要删除的节点
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1"><li id="a">JavaScript</li><li id="b">jquery</li><li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//找到JavaScript所在
var node = con.firstChild; //找到ul的第一个子节点
con.removeChild(node);
</script>
</body>
</html>
删除JavaScript所在的节点。
效果:
替换节点replaceChild()
实现子节点的替换。
格式:node.replaceChild(newNode, oldNode)
其中,newNode为要替换(新创建的节点)的节点,oldNode为被替换的节点,node为它们的父节点。如果没父节点,node就表示要被替换的节点。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1"><li id="a">JavaScript</li><li id="b">jquery</li><li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//找到JavaScript所在
var node = con.firstChild; //找到ul的第一个子节点
//先创建一个新节点
var newNode = document.createElement("li");
newNode.innerHTML = "css";
con.replaceChild(newNode, node); //用新创建的节点去替换JavaScript所在的节点。
</script>
</body>
</html>
效果:
复制节点(cloneNode)
该方法接收一个参数,这个参数是一个布尔值。接收"true"时表示深复制,即复制节点及其以下的整个子节点树,也就说把这个节点和它的所有子节点均复制了。接收"false"时表示浅复制,只复制这个节点。复制后返回的节点属于文档所有,它并没有父节点,可以为其指定父节点,如使用appendChild、inserBefore()、replaceChild()将它添加到文档中。
Text类型
文本节点,是DOM结构中常见的节点类型。它表示的是可以照字面意思解释的纯文本内容。它的特点有:
- nodeType的值为3
- nodeName的值为#text
- nodeValue的值为它的文本内容
- parentNode是一个Element。(就是包含文本的元素节点)
创建文本节点
document.createTextNode()
创建文本节点。
格式:document.createTextNode("文本内容");
其中,创建一个文本节点,也需要同时创建一个元素节点来包含它,要将文本节点添加到指定地方,要用appendChild()或inserBefore()插入到节点的后面或前面。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript</title>
</head>
<body>
<ul id="u1"><li id="a">JavaScript</li><li id="b">jquery</li><li id="c">html</li>
</ul>
<script>
/* 在此处书写javascript代码 */
var con = document.getElementById("u1"); //找到指定节点。
//找到JavaScript所在
var node = con.firstChild; //找到ul的第一个子节点
//先创建这个新节点
var newNode = document.createElement("li"); //添加一个名的li的元素。
var newText = document.createTextNode("css"); //添加一个文本节点。
newNode.appendChild(newText); //将文本节点插入到某节点之后
//newNode.innerHTML = "css";
//插入节点
con.insertBefore(newNode, node); //将新节点插入到指定节点之前。
</script>
</body>
</html>
效果: