本章目录
什么是DOM
--概念
- DOM: 就是Document Object Model。
- 什么是Document?
在JS里,Document指的就是像html,xml这样的标记语言文档。
- 为什么要用标记语言?
因为JS只能操作对象,而结构化的标记语言把它元素(比如<div>内容</div>)转成JS对象也比较方便,所以使用标记语言。
JS在操作文档时,要把元素转换为对象。
- 转成对象后能做什么?
转成对象后就能够操作对象,改变标签属性,改变标签内容,改变标签样式。
DOM的使用
DOM可以将页面元素转为JS对象,有两种方法转成对象:
--1.通过利用标签名,id,name方式来转换对象。(通过标签名一次转多个对象,id一次转1个对象,name一次转多个对象)具体使用下面方法:
- var 对象名 = document.getElementsByTagName("标签名");
- var 对象名 = document.getElementById("Id名");
- var 对象名 = document.getElementsByName("元素名");
可以将元素转换为对象,转了以后元素的属性将自动转为对象的属性。
转成对象后可以改变对象的属性,内容,进而改变元素的属性,内容。
注意:在转对象所用的标签,ID,元素名必须是在前面出现的,不然不能找到。
--使用元素属性,改变元素属性的方法
转成对象后,元素的属性将自动转为对象的属性,可以直接引用,例如:
- <body>
- <a id="alink" href="www.baidu.com" target="_blank" title="this is a test!">test</a>
- </body>
- </html>
- <script type="text/javascript">
- var aobj = document.getElementById("alink"); //通过Id转为对象
- alert(aobj.title); //通过对象属性引用元素属性
- aobj.title = "test finished!"; //通过对象属性改变元素属性
- //此时元素的title属性已经成了"test finished!"
- </script>
查看页面源代码:
此时title属性的值已经是"test finished!"
如果这个属性是本来没有的,那么会在原来元素中添加该属性。
--改变元素(非表单元素)内容的方法
利用对象属性(innerText,innerHTML,textContent),有两种方法可以改变元素的内容:
- 1.只读取,改变文本,不能添加、读取HTML标签:innerText(ie使用),textContent(火狐使用)
innerText的使用例子:
- <html>
- <body>
- <a id="alink" href="www.baidu.com" target="_blank" title="this is a test!">test</a>
- </body>
- </html>
- <script type="text/javascript">
- var aobj = document.getElementById("alink");
- aobj.innerText = "broTher";
- </script>
在ie中,innerText可以改变元素的属性,如图:
在火狐中,innerText不能改变元素的属性,如图:
使用innerText,所有HTML标签将被视为文本,如下例:
- <body>
- <a id="alink" href="www.baidu.com" target="_blank" title="this is a test!">test</a>
- </body>
- </html>
- <script type="text/javascript">
- var aobj = document.getElementById("alink");
- aobj.innerText = "<b>broTher</b>"; //在innerText的值中有<b>标签,但被视为文本
- </script>
虽然innerText里面有<b>标签,<b>标签也被视为文本的一部分,如图:
- 2.可以从内容中读取,在内容中添加HTML标签:innerHTML。
内容中添加标签的例子:
- <body>
- <a id="alink" href="www.baidu.com" target="_blank" title="this is a test!">test</a>
- </body>
- </html>
- <script type="text/javascript">
- var aobj = document.getElementById("alink");
- aobj.innerHTML = "<b>broTher</b>"; //<b>将被浏览器作为标签
- </script>
在浏览器中<b>将被解释为标签,如图:
读取内容中的标签:
- <body>
- <a id="alink" href="www.baidu.com" target="_blank" title="this is a test!"><b>test</b></a>
- </body>
- </html>
- <script type="text/javascript">
- var aobj = document.getElementById("alink");
- alert(aobj.innerHTML);
- </script>
可以读到<b></b>,如图:
总结:简单的说,就是innerHTML可以往内容里读写带HTML标签的数据,innerText只能往内容里写文本数据。
由于innerText存在浏览器兼容问题,所以推荐使用innerHTML.
- 读取整个元素的内容:outerText,outerHTML
--获取、改变表单value的方法
利用对象属性(value),可以获取、改变表单的内容。
- 获取表单的内容
- <input id="un" type="text" name="username" value="zhangsan"></ br>
- <script language = "javascript" type = "text/javascript">
- var username = document.getElementById("un");
- alert(username.value);
- </script>
页面输出结果是:
- 改变表单的内容
- <input id="un" type="text" name="username" value="zhangsan"></ br>
- <script language = "javascript" type = "text/javascript">
- var username = document.getElementById("un");
- username.value = "ddd";
- </script>
页面输出结果是:
表单的值已经成为ddd.
还例如:
- <textarea id="un">dddd</textarea>
- <script language = "javascript" type = "text/javascript">
- var username = document.getElementById("un");
- alert(username.value);
- </script>
执行结果如下:
--获取、改变元素的样式
- 使用对象属性(style),可以获取和改变元素的样式。
注意:对象名.style仍然是一个对象,在style里面有很多属性值可以设置。例如:
- aobj.style.backgroundColor = "red";//在css中背景颜色是background-color
- //在JS中"-"去掉,改成后面一个单词的首字母大写
- aobj.style.fontSize = "3cm";
在获取元素样式的时候,直接使用对象名.style只能获取内联样式(外部和嵌入样式都获取不了)。
因此,获取宽度通常使用可视宽度属性 "对象名.style.offsetWidth"获取宽度。
- 使用style属性只适合于改变单个样式,如果要改变多个样式,可以用className属性,给元素添加类,然后在css中写出该类的内容,就做到了给元素添加样式。
例如:
- <style>
- .test {
- width:500px;
- height:600px;
- border:2px;
- }
- </style>
- aobj.className = "test";//如果要加2个类test和demo,可以用aobj.className = "test demo";
--2.通过数组获取对象
遍历document对象的方法:
- var pro="";
- for(pro in document)
- {
- document.write("document."+pro+"="+document[pro]+"<br>");
- }
//下面是document对象中的一些是数组的属性。
- document.all=[object] //html文档中所有元素
- document.embeds=[object] //所有动画
- document.scripts=[object] //所有脚本
- document.applets=[ojbect] //所有java applet
- document.p_w_picpaths=[object] //所有图片
- document.forms=[object] //所有表单
- document.anchors=[object] //所有锚点,所谓锚点就是带name的a标签
- document.styleSheets=[object] //所有样式
- document.links=[object] //所有链接
用数组获取对象示例:
- <form name="frm1">
- <input type="text" name="username" value="zhangsan"></ br>
- </form>
- <form name="frm2">
- <input type="text" name="username" value="lisi"></ br>
- </form>
- <form name="frm3">
- <input type="text" name="username" value="admin"></ br>
- </form>
- <script>
- //访问元素属性的7种方法
- alert(document.forms[1].username.value);//通过索引数组
- alert(document.forms["frm2"].username.value);//通过关联数组,生成forms[]数组时同时生成了索引和关联成员
- alert(document.forms.item(1).username.value);//通过item函数,对象数组都有item()方法
- alert(document.forms.item("frm2").username.value);//通过item函数
- alert(document.forms.frm2.username.value);//通过对象成员的方式,JS中对象成员和数组方式可以互换
- alert(document.frm2.username.value);//通过对象成员frm2(因为是名字,所以可以不用写上级元素名)
- alert(document["frm2"].username.value);//通过关联数组
- </script>
说明:
为什么alert(document.forms[1].username.value)中username又不是frm2的属性,怎么直接就成为了frm2的子对象?
- 首先username是个元素的name,而在JS中如果元素有name,就可以直接把它的name当做对象名使用(虽然一般使用getElementsByname)。所以,username是个对象。
- JS中子元素都是上级元素(可以是父,甚至可以是祖先元素)的子对象,所以username是frm2的子对象(下面的document.frm2也是同理,frm2是document的子对象)。
Model的含义
DOM的M表示Model,即模型,这个模型是将html文档看成一棵树,每个部分(元素,内容,属性,注释)都是一个node(节点),<html></html>是根node。
只要知道一个节点,按关系找到其他节点。
例如下面的html文档:
- <html>
- <head>
- </head>
- <body>
- <div>
- wwww
- </div>
- <form>
- <input>
- <textarea></textarea>
- <select>
- </form>
- </body>
- </html>
转换成Model树后:
父节点:parentNode
子节点(第1个,最后1个):childNodes firstChild lastChild
同胞节点(上一个,下一个):nextSibling previousSibling
每个节点都拥有包含着关于节点某些信息的属性,这些属性是:
- nodeName 节点名称
- nodeValue 节点值
- nodeType 节点类型
nodeName属性含有节点的名称:
- 元素节点的nodeName是标签名称
- 属性节点的nodeName是属性名称
- 文本节点的nodeName永远是#text
- 文档节点的nodeName永远是#document
注释:nodeName所包含的XML元素的标签名称永远是大写的。
- 对于文本节点,nodeValue属性包含文本。
- 对于属性节点,nodeValue属性包含属性值。
- nodeValue属性对于文档节点和元素节点是不可用的。
nodeType属性可返回节点的类型:
类型 类型号
- 元素 1
- 属性 2
- 文本 3
- 注释 8
- 文档 9
文档流
所谓Html文档流,就是一个Html页面被解析的过程,页面从上到下被解析完文档流就结束了。
用document.write可以在文档流之中插入内容,但当文档流结束时,就无法在文档流中写入内容。比如在文档末尾添加:
- <a href="javascript:test()">add</a>
- <javascript>
- function test(){
- document.write("##############<br>");
- document.write("##############<br>");
- }
- </javascript>
点击add后,不会在当前页面末尾加上2行################,而是会在新页面中输出2行##################。
结论:
不能以输出的方式在已经结束的文档流中添加内容。
--在文档流中创建节点
- document.createElement("元素名") //创建元素
- // 例如:aobj = document.createElement("h1");
- //函数返回创建的对象。
--在文档流中追加节点
- 插入子节点
可以使用appendChild()函数给文档流的某个节点的子节点列表的末尾添加新的子节点。格式如下:
- 要在哪个对象下追加.appendChild(被追加的对象)
比如在对象one下追加aobj对象,就是如下:
- <div id="one"> </div>
- one = document.getElementById("one");
- one.appendChild(aobj); //aobj也是获取的对象
- 插入兄弟节点
可以使用insertBefore()函数在文档流的某个节点前插入节点。格式如下:
- insertBefore(newchild,refchild)
- //newchild 插入新的节点
- //refchild 在此节点前插入新节点
例如:robj.insertBefore(newobj,robj); //在robj前面插入节点newobj
--从文档流中删除节点
- 删除子节点
- nodeObject.removeChild(node)
- //node 必需。指定需要删除的节点。
注释:
Internet Explorer 会忽略节点间生成的空白文本节点(例如,换行符号),而 Mozilla 不会这样做。因此,在下面的例子中,我们会使用一个函数来检查最后一个子节点的节点类型。
- //check if last child node is an element node
- function get_lastchild(n)
- {
- var x=n.lastChild;
- while (x.nodeType!=1)
- {
- x=x.previousSibling;
- }
- return x;
- }
- xmlDoc=loadXMLDoc("books.xml");
- var x=xmlDoc.getElementsByTagName("book")[0];
- deleted_node=x.removeChild(get_lastchild(x));
- document.write("Node removed: " + deleted_node.nodeName);
上面代码片段可删除首个 <book> 元素中的最后一个子节点。