DOM(Document Object Model)即文档对象模型,针对HTML和XML文档的API(应用程序接口)。DOM描绘了一个层次化的节点树,运行开发人员添加、移除和修改页面的某一部分。DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML),但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。
一.DOM介绍
DOM中的三个字母,D(文档)可以理解为整个Web加载的网页文档;O(对象)可以理解为类似window对象之类的东西,可以调用属性和方法,这里我们说的是document对象;M(模型)可以理解为网页文档的树型结构。
DOM有三个等级,分别是DOM1、DOM2、DOM3,并且DOM1在1998年10月成为W3C标准。DOM1所支持的浏览器包括IE6+、Firefox、Safari、Chrome和Opera1.7+。
PS:IE中的所有DOM对象都是以COM对象的形式实现的,这意味着IE中的DOM可能会和其他浏览器有一定的差异。
HTML中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>hello world</p>
</body>
</html>
文档元素(文档的最外层的元素):<html>
文档中,只能有一个文本元素。HTML的文档元素永远为<html>元素,而XML没有预定义的外层结构,所有任何元素都能为文档元素。
1.查找元素
元素节点方法
方法 说明
getElementById() 获取特定ID元素的节点
getElementsByTagName() 获取相同元素的节点列表
getElementsByName() 获取相同名称的节点列表
getAttribute() 获取特定元素节点属性的值
setAttribute() 设置特定元素节点属性的值
removeAttribute() 移除特定元素节点属性
例如:
<div id="box">
this is div
</div>
1.1 getElementById()方法
getElementById()方法,接受一个参数:获取元素的ID。如果找到相应的元素则返回该元素的HTMLDivElement对象,如果不存在,则返回null。
var box = document.getElementById('box');
console.log(box);
//<div id="box">
// this is div
//</div>获取id为box的元素节点
PS:如果DOM没有加载完成,默认情况返回null,这无关是否存在id="box"的标签,而是执行顺序问题。
解决方法:
1.把script调用标签移到html末尾即可;
2.使用onload事件来处理JS,等待html加载完毕再加载onload事件里的JS。
window.onload = function () { //预加载html后执行
document.getElementById('box');
};
PS:id表示一个元素节点的唯一性,不能同时给两个或以上的元素节点创建同一个命名的id。某些低版本的浏览器会无法识别getElementById()方法,比如IE5.0-,这时需要做一些判断,可以结合上章的浏览器检测来操作。
if (document.getElementById) { //判断是否支持getElementById
alert('当前浏览器支持getElementById');
}
当我们通过getElementById()获取到特定元素节点时,这个节点对象就被我们获取到了,而通过这个节点对象,我们可以访问它的一系列属性。
元素节点属性
属性 说明
tagName 获取元素节点的标签名
innerHTML 获取元素节点里的内容,非W3C DOM规范
document.getElementById('box').tagName; //DIV
document.getElementById('box').innerHTML; // this is div(注意前后是有空格的,因为原div中就是有空格的)
HTML属性的属性
属性 说明
id 元素节点的id名称
title 元素节点的title属性值
style CSS内联样式属性值
className CSS元素的类
document.getElementById('box').id; //获取id
document.getElementById('box').id = 'person'; //设置id
document.getElementById('box').title; //获取title
document.getElementById('box').title = '标题' //设置title
document.getElementById('box').style; //获取CSSStyleDeclaration对象
document.getElementById('box').style.color; //获取style对象中color的值
document.getElementById('box').style.color = 'red'; //设置style对象中color的值
document.getElementById('box').className; //获取class
document.getElementById('box').className = 'box'; //设置class
alert(document.getElementById('box').bbb); //获取自定义属性的值,非IE不支持
1.2 getElementsByTagName()方法
<p>this is p1</p>
<p>this is p2</p>
<p>this is p3</p>
getElementsByTagName()方法将返回一个对象数组HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。
document.getElementsByTagName('p'); //HTMLCollection:[p, p, p]获取所有元素
document.getElementsByTagName('p'); //获取所有p元素,返回数组
document.getElementsByTagName('p')[0]; //<p>this is p1</p>,获取第一个p元素
document.getElementsByTagName('p').item(0) //<p>this is p1</p>,获取第一个p元素
document.getElementsByTagName('p').length; //3,获取所有p元素的数目
PS:不管是getElementById还是getElementsByTagName,在传递参数的时候,并不是所有浏览器都必须区分大小写,为了防止不必要的错误和麻烦,我们必须坚持养成区分大小写的习惯。
1.3 getElementsByName()方法
getElementsByName()方法可以获取相同名称(name)的元素,返回一个对象数组HTMLCollection(NodeList)。
document.getElementsByName('add') //获取input元素
document.getElementsByName('add')[0].value //获取input元素的value值
document.getElementsByName('add')[0].checked //获取input元素的checked值
PS:对于并不是HTML合法的属性,那么在JS获取的兼容性上也会存在差异,IE浏览器支持本身合法的name属性,而不合法的就会出现不兼容的问题。
1.4 getAttribute()方法
getAttribute()方法将获取元素中某个属性的值。它和直接使用.属性获取属性值的方法有一定区别。
document.getElementById('box').getAttribute('id');//获取元素的id值
document.getElementById('box').id; //获取元素的id值
document.getElementById('box').getAttribute('mydiv');//获取元素的自定义属性值
document.getElementById('box').mydiv //获取元素的自定义属性值,非IE不支持
document.getElementById('box').getAttribute('class');//获取元素的class值,IE不支持
document.getElementById('box').getAttribute('className');//非IE不支持
PS:HTML通用属性style和onclick,IE7更低的版本style返回一个对象,onclick返回一个函数式。虽然IE8已经修复这个bug,但为了更好的兼容,开发人员只有尽可能避免使用getAttribute()访问HTML属性了,或者碰到特殊的属性获取做特殊的兼容处理。
1.5 setAttribute()方法
setAttribute()方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。
document.getElementById('box').setAttribute('align','center');//设置属性和值
document.getElementById('box').setAttribute('bbb','ccc');//设置自定义的属性和值
PS:在IE7及更低的版本中,使用setAttribute()方法设置class和style属性是没有效果的,虽然IE8解决了这个bug,但还是不建议使用。
1.6 removeAttribute()方法
removeAttribute()可以移除HTML属性。
document.getElementById('box').removeAttribute('style');//移除属性
PS:IE6及更低版本不支持removeAttribute()方法。
2.Node类型
元素节点 Node.ELEMENT_NODE(1)
属性节点 Node.ATTRIBUTE_NODE(2)
文本节点 Node.TEXT_NODE(3)
CDATA节点 Node.CDATA_SECTION_NODE(4)
实体引用名称节点 Node.ENTRY_REFERENCE_NODE(5)
实体名称节点 Node.ENTITY_NODE(6)
处理指令节点 Node.PROCESSING_INSTRUCTION_NODE(7)
注释节点 Node.COMMENT_NODE(8)
文档节点 Node.DOCUMENT_NODE(9)
文档类型节点 Node.DOCUMENT_TYPE_NODE(10)
文档片段节点 Node.DOCUMENT_FRAGMENT_NODE(11)
DTD声明节点 Node.NOTATION_NODE(12)
可以利用nodeType属性来得出此节点类型多对应的数值。
a.nodeType==1表示a为一个元素。
例如:
var box = document.getElementById("box");
if(box.nodeType == 1){
alert("this is a element")
}
2.1 nodeName和nodeValue
nodeName:对于元素节点nodeName为元素名;
nodeValue:对于元素节点nodeValue永远为null
例如:
var box = document.getElementById("box");
if(box.nodeType == 1){
console.log(box.nodeName)//DIV
console.log(box.nodeValue)//null
}
2.2 节点关系
2.2.1childNode
<div id="box"><p>asdasdasdasd</p>
<a href="###">321asd132as1d3a2s1d</a>
</div>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.childNodes);
//[p, text, a, text]
// p和a元素之间有text是因为他们之间用enter进行了换行
// childNodes属性中包含有NodeList属性(类数组但是不是数组)。NodeList中包含着所有的子元素,可以
console.log(box.childNodes[0])//<p>asdasdasdasd</p>
console.log(box.childNodes.item(0))
//item()是一种方法
console.log(box.childNodes.length)
</script>
2.2.2.将NodeList转化为数组
<script type="text/javascript">
var box = document.getElementById("box");
// box.childNodes.NodeList属性和arguments属性很像都可以用Array.prototype.slice方法将其转换为数组
var a = Array.prototype.slice.call(box.childNodes,0);
console.log(a)//[p, text, a, text]
// 但是以上的代码在IE8以及之前是不能运行的。
// 兼容版:
function converToArray(nodes){
var array = null;
try{
array = Array.prototype.slice.call(box.childNodes,0);//针对非IE
}catch(ex){
array = new Array();
for(var i = 0;i<nodes.length;i++){
array.push(nodes[i])
}
}
return array;
}
// converToArray方式首先用最简单的放法,如果报错的话再用push
</script>
2.2.3.层次节点属性
节点的层次结构可以划分为:父节点与子节点、兄弟节点这两种。当我们获取其中一个元素节点的时候,就可以使用层次节点属性来获取它相关层次的节点。
属性 说明
childNodes 获取当前元素节点的所有子节点
firstChild 获取当前元素节点的第一个子节点
lastChild 获取当前元素节点的最后一个子节点
ownerDocument 获取该节点的文档根节点,相当与document
parentNode 获取当前节点的父节点
previousSibling 获取当前节点的前一个同级节点
nextSibling 获取当前节点的后一个同级节点
attributes 获取当前元素节点的所有属性节点集合
<div id="box"><p>asdasdasdasd</p>
<a href="###" id="aa">321asd132as1d3a2s1d</a>
</div>
<script type="text/javascript">
var a = document.getElementById("aa");
2.2.3.1.parentNode
// 指向该元素的父元素
console.log(a.parentNode);
// 指向的是div,会打印出整个div,包括它包裹的元素
// <div id="box"><p>asdasdasdasd</p>
// <a href="###" id="aa">321asd132as1d3a2s1d</a>
// </div>
2.2.3.2.previousSibling
//前一个兄弟节点,第一个元素的该属性为null
console.log(a.previousSibling)
//#text
2.2.3.3.nextSibling
//后一个兄弟节点,最后一个元素的改属性为null
console.log(a.nextSibling)
//#text
2.2.3.4.firstChild,lastChild
// firstChild:父元素的第一个子元素
// lastChild:最后一个子元素
var box = document.getElementById("box");
console.log(box.firstChild);
//<p>asdasdasdasd</p>
console.log(box.lastChild)
//#text
</script>
在看一个div是否为空时,可以用2.层次节点属性hasChildNodes(),这个属性在包含有1个或者多额子元素时返回true,
2.3.操作节点
节点操作方法
方法 说明
write() 这个方法可以把任意字符串插入到文档中
createElement() 创建一个元素节点
appendChild() 将新节点追加到子节点列表的末尾
createTextNode() 创建一个文件节点
insertBefore() 将新节点插入在前面
repalceChild() 将新节点替换旧节点
cloneNode() 复制节点
removeChild() 移除节点
2.3.1.write()方法
write()方法可以把任意字符串插入到文档中去。
document.write('<p>这是一个段落!</p>')' ; //输出任意字符串
2.3.2.createElement()方法
createElement()方法可以创建一个元素节点。
document.createElement('p'); //创建一个元素节点
2.3.3.appendChild
向一个元素的尾部添加新的元素
<div id="box"><p>asdasdasdasd</p>
<a href="###" id="aa">321asd132as1d3a2s1d</a>
</div>
<p id="pp">hcd</p>
<script type="text/javascript">
var box = document.getElementById("box");
var p = document.getElementById("pp");
var a = box.appendChild(p)
console.log(a)
//<p id="pp">hcd</p>,appendChild()返回的是新增节点
console.log(box)
//box外面的p元素不见了,而是增加到了box中,
</script>
2.3.4.createTextNode()方法
createTextNode()方法创建一个文本节点。
var text = document.createTextNode('段落'); //创建一个文本节点
p.appendChild(text); //将文本节点添加到子节点末尾
我们平时用的时候可以createElement创建新的元素,createTextNode创建文本节点,appendChild将文本节点插入到元素节点中,appendChild再将元素插入到我们想要的地方。
2.3.5.insertBefore
参数1:新增的元素
参数2:插入到哪个元素前面
<div id="box"><p>asdasdasdasd</p>
<a href="###" id="aa">321asd132as1d3a2s1d</a>
</div>
<p id="pp">hcd</p>
<script type="text/javascript">
var box = document.getElementById("box");
var p = document.getElementById("pp");
var a = document.getElementById("aa");
var b = box.insertBefore(p,a)
console.log(b)
//返回新增节点
console.log(box)
//div外的p将会移到a元素前面
</script>
2.3.6.replaceChild替换子元素
参数1:新增的元素
参数2:要被提换的元素
利用2的例子
var b = box.replaceChild(p,a)
2.3.7.removeChild移除元素
box.removeChild(a)
2.3.8.cloneNode复制
1.深度复制
var b = box.cloneNode(true);
console.log(b)
//和box元素一样,子元素也会被复制;
2.浅复制
var b = box.cloneNode(true);
console.log(b)
//只会复制box元素即div元素,子元素不会被复制
注意:不会复制js属性和方法;但是ie有bug,会复制属性和方法
二.Document元素:
文档,并且是widnow的一个属性
特点:
nodeType:9;
nodeName:#document;
nodeVale:null;
parentNode:null
1.document.documentElement
将<html>内的打印出来
2.document.title
console.log(document.title)
//打印文档的标题
document.title = "new title";
//设置文档的标题
3.
console.log(document.URL)
//获取完整的URL
console.log(document.domain)
//获取域名
console.log(document.referrer)
//来源页面的URL
其中只有domain是可以设置的;但是设置的时候有要求:
不能将这个属性设置为URL中没有的包含的域。
如www.xp.com
那么只能设置为xp.xom
利用domain设置跨域也是很方便的
如www.xp.com和p2p.xp.com
可以将这两个页面的domain都设置为
xp.xom;但是注意设置过一遍后,就不能再设置了,哪怕是设置回去也不行。
4.特殊集合
document.anchors:文档中所有带有name属性的a标签
document.forms:文档中所有的form元素
document.images:文章中所有的img元素
三.Element元素用来表现HTML或者XML元素
nodeType:1;
nodeName:元素的名字;
nodeValue:null;
parentNode:Document或Element
要访问元素的标签名时,可以使用nodeName属性,也可以使用tagName属性。(但是注意返回的是大写)
例如:
<div id="box"><p>asdasdasdasd</p>
<a href="###" id="aa">321asd132as1d3a2s1d</a>
</div>
<p id="pp">hcd</p>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.tagName)//DIV
console.log(box.nodeName)//DIV
</script>
因为返回的是大写,所以再写一些判断的时候可以采用下面的方式:
if(element.tagName.toLowerCase() == "div"){
}
1.HTML元素
可以拥有以下属性:
id:元素的唯一标示;
className:元素指定的类;
title:有关元素的附加说明;一般通过工具条表示
lang:语言标示
dir:语言的方向
2.取的特性
getAttribute()获取属性
setAttribute()设置属性
removeAttribute()移除属性
例如:
<div id="box" class="className" title="this is box" leng="en" dir="ltr" data-hcd="hcd" style="background:red;width: 200px;height: 200px;"></div>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.getAttribute("id")) //"box"
console.log(box.getAttribute("class")) //"className"
console.log(box.getAttribute("data-hcd")) //"hcd"
console.log(box.getAttribute("asdasd")) //"null"
console.log(box.getAttribute("style")) //"background:red;width: 200px;height: 200px;"
console.log(box.id)//"box"
console.log(box.style)//一个cssstyle对象
</script>
上面的代码用来获取元素的属性,包括自定义属性,如果没有该属性就返回null。
对于行内样式style,利用getAttribute返回的是css样式文本,利用属性来访问返回的却是一个对象。
同样对于onclick,利用getAttribute返回的是onclick内的代码字符串,利用属性来访问返回的却是一个函数。
由于这些差异,所以一般不会用getAttribute访问属性,而是使用对象属性(如:box.id),只用自定义属性采用getAttribute
3.设置属性
通过box.setAttribute("id","newId");
也可以通过box.id = "newId"来进行设置。
但是通过以上的两种方法是不能够新增属性的。
采用setAttribute方法会在IE7之前存在异常(name和style不能够设置),所以一般通过box.id = 的方法设置。
removeAttribute()
不仅会移除属性值,连属性也会一起移除
4.attributes
元素有attributes属性,attributes属性中有NamedNodeMap,与NodeList类似,元素的每一个属性都作为一个attr节点存在NamedNodeMap中;
例如:
<div id="box" class="className" title="this is box" leng="en" dir="ltr" data-hcd="hcd" style="background:red;width: 200px;height: 200px;"></div>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.attributes)//NamedNodeMap0:id 1:class 2:title 3: leng 4:dir 5:data-hcd 6:style length:7 __proto__: NamedNodeMap
</script>
我们可以通过遍历将元素所有的所有属性以name:vale的方式打印出来。但是IE7会有问题,就是会返回所有的可能属性,不仅是自己设置的,是所有的。而自己设置的属性都会自动有specified属性,只要该属性为true就是用户自己设置的。
function outputAttributes(element){
var pairs = new Array(),
attrName,
attrValue,
i;
for(i = 0,i < element.attributes.length;i++){
attrName = element.attributes[i].nodeName;
attrValue =
element.attributes[i].nodeValue;
if(element.attributes[i].specified){
pairs.push(attrName + "=\""+attrValue+"|"")
}
}
return pairs.join("");
}
5.创建元素
document.createElement()
var div = document.createElement("<div id="newBox">this is div</div>")
6.获取子节点
<ul id="ulbox">
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<script type="text/javascript">
var ul = document.getElementById("ulbox");
// 1.通过下面的方法获取ul的子元素,由于有enter键导致的分行,所以会有text元素
for(var i = 0;i < ul.childNodes.length;i++){
console.log(ul.childNodes[i])
}
// #text
// <li>a</li>
// #text
// <li>b</li>
// #text
// <li>c</li>
// #text
// 2.只获取ul下的li,nodeType==1表示为元素
for(var i = 0;i < ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType==1){
console.log(ul.childNodes[i])
}
}
// <li>a</li>
// <li>b</li>
// <li>c</li>
// 3.可以通过下面的方法获取到ul下li的集合
var items = ul.getElementsByTagName("li")
console.log(items)
</script>
四.Text类型
表示的是纯文本内容,不含有HTML代码。
nodeType:3;
nodeName:#text;
nodeBValue:节点包含的而所有文本;
可以使用的方法:
1.appendDate(text):将text添加到节点的尾部
2.deleteDate(offset,count):从offset位置开始删除count个字符。
3.insertDate(offset,text):从offset位置前插入text、
4.replaceDate(offset,count,text):用text替换offset开始到offset+count位置的字符(前闭后开)。
5.splitText(offset):从offset指定的位置将当前文本节点分成两个文本节点。
6.substringDate(offset,count):提取从offset到offset+count处的字符。
<div></div> //不含有文本节点
<div> </div> //含有文本节点空格
<div>阿萨德 爱谁谁的</div>//含有文本节点“阿萨德 爱谁谁的”
可以设置文本节点,但是会进行HTML转义。
如:
var box = document.getElementById("box");
var text = box.childNodes[0];
text.nodeValue = "<strong>asd</strong>"
//输出结果为加粗版额asd
1.创建文本节点
document.createTextNode();
例如:
<div id="box"></div>
<script type="text/javascript">
var box = document.getElementById("box");
var text = document.createTextNode("pppp");
box.appendChild(text);
var textb = document.createTextNode("ooooo");
box.appendChild(textb);
console.log(box.childNodes.length);
//2
box.normalize();
console.log(box.childNodes.length);
//1
</script>
创建2个text节点插入到div中,这时div的childNodes为2个,使用normalize()方法可以将这两个text节点合并