DOM技术
DOM概述
DOM:Document Object Model(文档对象模型)(DOM核心就是 文档变对象,标签也变对象,属性也变对象,反正就是把标记文档拆散)
用来将标记型对象封装成对象,并将标记型文档中的所有内容(标签,文本,属性)都封装成对象。
封装成对象的目的是为了方便操作这些文档和文档中的内容,方便动态(增删改查)。
文档:标记型文档
对象:封装了属性和行为的实例
模型:所有标记型文档都具备的一些共性特征的一个体现
只要是标记型文档,DOM技术都可以进行操作。
常见的标记型文档:html xml
DOM这种技术如何对标记型文档进行操作的?
首先对标记型文档进行解析。
DOM解析方式
将标记型文档解析成一个DOM树,并将树中的内容封装成节点对象
在浏览器中,DOM解析将按照标签的层次关系体现出标签的所属,形成一个树状结构,称为DOM树。
DOM解析由浏览器自动完成,解析之后,生成一个document对象,并将它加载进内存。
比如下面这个html文档和相应的DOM树,整个HTML文档被封装成一个document对象。
<html> <head> <title>这是演示文档</title> </head> <body> <div>div区域</div> <dl> <dt>上层项目</dt> <dd>下层项目</dd> </dl> <table> <tbody> <tr> <th>表头</th> <td>单元格</td> </tr> </tbody> </table> <form> <input type="text"/> </form> </body> </html>
DOM树:
树中的标签,文本,和属性称为节点,也称为对象。标签也称为页面中的元素。乱
理解:html标签是静态的,全是死的,没有办法对其中的某个标签进行操作的,现在通过DOM技术把标签,文本,属性全部单个拿出来,那么文档就可以对每个元素进行操作
DOM技术把文档文档中的元素全变成对象,这样才能挨个的动态操作。
DOM解析方式的好处:可以对树中的节点进行任意操作,比如:增删改查。
弊端:这种解析方式需要将真个标记型文档加载进内存,意味着如果标记型文档的体积很大,浪费较大内存空间。
SAX解析方式
是由一些组织定义的民间常用的解析方式,并不是w3c标准,而DOM是w3c的标准。
SAX解析方式:是基于事件驱动的解析。
这种解析方式,并不将整个文档一次性读取,按照每一个标签进行解析,读到一个标签的开头,相当于处罚一个事件,然后对标签内容进行解析,然后读取到结束标签,这个解析就完成了。
这种解析方式获取数据速度很快(查),但是不能对标记进行增删改的动作。根据需求来灵活选择。
DOM的三级模型
DOM level 1:将html文档封装成对象。
DOM level 2:在level 1 基础上加入新功能,比如解析名称空间(html标签中的xmln属性代表命名空间,这个名字必须唯一,一般用网站的域名来作为命名空间,)
DOM level 3:将xml文档封装成对象。
这三种就完成了对常见的标记文档的解析
DOM是一种底层的技术,各个语言都对外提供了DOM的解析工具,java中的dom4j,jaxp(java内置)
同样Javascript也有相应的解析工具,在前端中,用Javascript进行解析。
DHTML概述
动态的HTML,不是一门语言,是多项技术综合体的简称
html+css只是一个静态页面,加入Javascript和DOM之后,就动起来了。
这四个技术在动态html页面效果定义时,都属于什么角色呢,负责什么职责呢?
HTML:负责提供标签,对数据进行封装,目的是便于对该标签中的数据进行操作。(用标签封装数据)
CSS:负责提供样式属性,对标签中的数据进行样式的定义。(对数据进行样式定义)
DOM:负责将标记型文档以及文档中的所有内容进行解析,并封装成对象,在对象中定义了更多的属性和行为,便于对对象操作。
Javascript:负责提供程序设计语言,对页面中的对象进行逻辑操作。比如想添加十个节点,就用循环,不然要挨个添加,甚是麻烦!(负责页面行为,就是页面动态效果)
综上所述:Javascript是动态效果的主力编程语言。
DHTML+XMLhttpRequest = AJAX
BOM模型
Browser Object Model(浏览器对象模型)
DOM为了方便操作文档,BOM为了方便操作浏览器。
bom中有一些对象,这些对象可以直接在javascript代码中使用,用来获取相应的信息。
window对象
浏览器对应的对象就是window对象
注意:只要打开浏览器,window对象就在内存中,可以在javascript中直接使用,其实由于window对象是默认存在的,所以window对象可以缺省
appName,history,navigator等属性。
一些常用方法:
alert();弹窗
confirm();弹出一个是否选择窗口,根据不同的选择,该函数返回是或否,通过对该返回值的判定,进而选择执行不同的操作。(if操作)
focus();获取焦点。
setTimeout(js语句,毫秒值);超过毫秒值就执行js语句。类似于单片机的中断?函数返回一个整数,用来区分多个计时,将该值放到clearTimeout中可以取消该计时
setInterval(js语句,毫秒值);每隔毫秒值执行一次。函数返回一个整数,用来区分多个计时,将该值放到clearInterval中可以取消该计时
clearTimeout();
clearInterval();
moveBy(横坐标偏移量,纵坐标偏移量);当前浏览器窗口按照偏移量移动。
moveTo(横坐标,纵坐标);直接移动到指定坐标点。
open("网址","打开方式","height=100,width=100,status=yes,toolbar=yes,menubar=yes,location=yes");打开方式:新窗口(_blank),有状态栏,有工具栏,有菜单栏,有地址栏
close();关闭窗口,必须是自己通过代码新打开的窗口才能通过close来关闭。
常见事件:
直接指向一个函数即可,事件触发时,就会执行函数。
onload=function(){
code...
}
onload:当窗口中的所有动作完成后,立刻触发,网页内容加载完后执行。
unbeforeunload:点击关闭浏览器窗口,关闭之前会执行。
onunload:点击关闭浏览器窗口,浏览器关闭之后调用。
属性:
status:属性中的值就会显示在状态栏。
弹窗广告:
location对象
和java中的url对象类似,location中的属性可以获取,也可以赋值,相当于一个变量。
location.protocol:获取地址栏中的协议
location.href:可以对该变量赋值,这会改变地址栏的值并进行解析,如果解析是http协议,就会对链接进行访问。
location.pathname:路径名
DOM操作
节点的获取
通过document直接获取节点
通过document对象来操作标记文档,该对象将标记型文档中的各个节点对象进行了封装,通过document就可以获得各个节点。
用document对象中获取节点的方法:
1,getElementById();通过标签的ID来获取节点,返回该标签节点。
2,getElementsByName();//通过标签的name属性获取节点,因为name属性会重名,返回的是一个数组,注意,不是所有标签都具有name属性。
3,getElementsByTagName();//通过标签名来获取节点,同样的,标签名也会出现重复,返回值也是一个数组。
常见的节点有三种:1,标签型节点 节点类型:1
2,属性节点 节点类型:2
3,文本节点 节点类型:3
其中,标签型节点没有值,属性节点和文本节点是有值的。
节点的必备属性
节点是Object类型的,每个节点都有三个必备属性:
1,节点名称(DIV,INPUT等)
.nodeName
2,节点类型
.nodeType
3,节点值
.nodeValue
不同的节点还有其各自特殊的属性
例如:
div标签节点中的其他属性和方法:
.innerHTML div节点中的文本,可以用来获取区域的文本,对其赋值也可以改变div中的文本。
.getElementsByTagName();获取div标签下一级的节点,用来获取内部节点。由于div标签是容器型的标签,所以会有这个方法,但是并没有 getElementsByName()和getElementById()这两个方法,因为并不能保证每个内部标签都有name属性或者ID。
input标签节点中的其他属性:
.type
.name
.value 获取用户输入的内容,可以用来在客户端进行输入的校验,这个要与必备属性的nodeValue区分,由于是标签型节点,所以点没有值。
a节点中的属性和方法:
.innerHTML:获取超链接内容。
.target:target属性可设置或返回在何处打开表单中的 action-URL。
.eg:
<input type="button" value="演示document获取节点" onclick="Demo()" /> <script type="text/javascript"> function Demo(){ //获取页面中的div节点,用第一个方法 var divNode = document.getElementById("divid"); alert(divNode.nodeName+":"+divNode.nodeType+":"+divNode.nodeValue); var text = divNode.innerHTML; alert(text); divNode.innerHTML = "div文本区域被改变".fontcolor("red");//这样就可以改变字符串的颜色,记住 //获取文本框节点,用第二个方法 var nodes = document.getElementsByName("user");//返回的是一个数组 //或者可以直接获取这个数组的第一个元素 var userNode = document.getElementsByName("user")[0];//这是单独的一个元素 alert("length:"+nodes.length); alert("nodeName:"+nodes[0].nodeName); alert("nodeValue:"+nodes[0].nodeValue); alert("nodeType:"+nodes[0].nodeType); alert("type:"+nodes[0].type); alert("name:"+nodes[0].name); alert("value:"+nodes[0].value);
//通过标签名获取节点
var nodes = document.getElementsByTagName("a");
alert(nodes.length);
alert(nodes[0].innerHTML);
alert(nodes[0].href);
nodes[0].target = "_blank";
//获取内部节点
var divNode = document.getElementById("divId1");
var aNodes = divNode.getElementsByTagName("a");//返回数组
aNodes[0].target = "_blank";
alert(aNodes[0].innerHTML);
} </script> <div id = divid>这是一个div区域</div> <input type="text" name="user"/>
<a href="www.baidu.com">百度首页</a> <!--通过标签 tagname 获取该标签节点-->
<div id="divId1">
<a href="www.hao123.com">百度门户</a>
</div>
通过节点层次关系获取节点
直接获取的方法有弊端,并不是所有的节点都有ID或者name属性,这样获取节点麻烦。
节点之间的关系:父节点,子节点,兄弟节点,兄弟节点之间分上一个节点,下一个节点。
任何一个节点都有一些属性
.parentNode:由于父节点只有一个,所以属性就可以,对应一个节点对象
.childNodes:返回直接后代的一个集合,对应一个节点集合
.previousSibling:上一个兄弟节点,同样对应一个节点对象
.nextSibling:下一个兄弟节点,对应一个节点对象
TIPS:兄弟节点尽量少用,因为在不同的浏览器解析兄弟节点不一致,会导致兼容性问题,谷歌浏览器中,DOM的解析方式和IE不同,谷歌浏览器会把回车符解析为一个文本节点(#text),而IE浏览器会跳过空格,直接解析下一个节点,例如下面程序中的获子节点部分。
<html> <head> <title>这是演示文档</title> </head> <body> <input type="button" value="演示document获取节点" onclick="Demo()" /> <script type="text/javascript"> function Demo(){ var tabNode = document.getElementById("tabId"); //获取父节点 var parNode = tabNode.parentNode; alert("父节点:"+parNode.nodeName);//BODY //获取子节点 var chiNodes = tabNode.childNodes;//注意:表格的下一级标签默认是TBODY,就算不写,也会存在 alert("子节点:"+chiNodes[0].nodeName);//TBODY 在IE中显示TBODY 在谷歌浏览器中显示#text表示文本节点 alert("再下一节点:"+chiNodes[0].childNodes[0].nodeName);//按照层次结构点下去 //获取兄弟节点 var broNode = tabNode.previousSibling;//获取上一个兄弟节点,下一个类似 alert("上一个兄弟节点;"+broNode.nodeName); } </script> <div>div区域</div> <dl> <dt>上层项目</dt> <dd>下层项目</dd> </dl> <table id="tabId"> <tbody> <tr> <th>表头</th> <td>单元格</td> </tr> </tbody> </table> <form> <input type="text"/> </form> </body> </html>
节点的操作
操作无非增删改查,查上面已经解决了,现在解决增删改。
增
向div标签中添加文本
1,创建节点,利用的是document中的方法
var oTextNode = document.creatTextNode();创建一个文本节点。
2,获取div节点
var oDivNode = document.getElementById("div_1");div的ID是div_1
3,添加节点
var oDivNode.appendChild(oTextNode);向div节点oDivNode中添加文本节点。
向div标签中添加按钮节点
1,创建按钮节点
var oButtonNode = document.createElement("input");创建一个 imput 元素
oButtonNode.type = "button";设置节点的类型为按钮
oButtonNode.value = "自定义添加的按钮";设置按钮的文本
2,添加按钮节点
oDivNode.appendChild(oButtonNode);向div节点oDivNode中添加按钮节点
另外一种简单方法:
利用容器型标签的 innerHTML 属性来完成,这个非常强,innerHTML中的文本会按照html来解析
oDivNode.innerHTML = "犯我强汉,虽远必诛。" ;
oDivNode.innerHTML = "<input type='button' value=自定义按钮>" ;注意字符串中的双引号要用单引号代替
oDivNode.innerHTML = "<a href='www.baidu.com'>超链接</a>" ;
删
1,获取想要删除的节点
var oDivNode_1 = document.getElementById("div_1");div的ID是div_1
2,删除节点,要被删除的节点自己调用方法(这种方法较少使用,推荐使用下一个,这句代码在谷歌浏览器运行不了,ie可以。)
oRemoved = oDivNode_1 .removeNode(false);false代表只删除该div节点,true代表删除该节点和该节点下面的所有子节点,默认为false,返回值是被删 除的节点对象
2,一般使用removeChild()方法,这个方法是删除子节点,所以要先获取 要被删除的节点的父节点,然后用removeChild()方法删除节点本身。(通用)
oDivNode_1.parentNode.removeChild(oDivNode_1);父节点来删除自己
改(替换和克隆节点)
替换就是移动
1,获取两个节点,用div_3替换div_1
var oDivNode_1 = document.getElementById("div_1");div的ID是div_1div_1
var oDivNode_3 = document.getElementById("div_3");
2,替换
oDivNode_3.replaceNode(oDivNode_3);不建议使用,谷歌不支持
oDivNode_1.parentNode.replaceChild(oDivNode_3,oDivNode_1);用3替换1,新在前,旧在后,建议使用,通用的
克隆就是复制
用div_3替换div_1,并保留div_3
1,获取两个节点,并创建一个要保留节点的副本。
var oDivNode_1 = document.getElementById("div_1");div的ID是div_1div_1
var oDivNode_3 = document.getElementById("div_3");
var oCopyDivNode_3 = oDivNode_3.clone(false);创建副本,false代表只复制div区域,div区域下面的节点不复制,true则表示全部复制
2,用克隆出来的副本去替换div_1,仍然是用获取父节点来操作
oDivNode_1.parentNode.replaceChild(oCopyDivNode_3 ,oDivNode_1);
<html> <head> <title>这是演示文档</title> <style type="text/css"> div{ border:blue 1px solid ; width:300px; height:50px; padding:20px; margin:10px; } #div_1{ background-color:#00ccff; } #div_2{ background-color:#0199ff; } #div_3{ background-color:#0211ff; } #div_4{ background-color:#0366ff; } </style> </head> <body> <input type="button" value="创建并添加节点" onclick="crtAndAddNode()"/> <input type="button" value="删除节点" onclick="deleteNode()"/> <input type="button" value="修改节点" onclick="changeNode()"/> <script type="text/javascript"> function crtAndAddNode(){ //1,创建文本节点 var otextNode = document.createTextNode("秦时明月汉时关,万里长征人未还。"); //2,获取div_1节点 var oDivNode_1 = document.getElementById("div_1"); //3,将文本节点添加到div_1节点 oDivNode_1.appendChild(otextNode); //1,创建一个按钮节点 var oButtonNode = document.createElement("input"); oButtonNode.type = "button"; oButtonNode.value = "自定义添加的按钮"; //2,将按钮节点添加到div_1节点 oDivNode_1.appendChild(oButtonNode); //利用innerHTML,字符串中的内容会按照html来解析 var oDivNode_2 = document.getElementById("div_2"); var oDivNode_3 = document.getElementById("div_3"); var oDivNode_4 = document.getElementById("div_4"); oDivNode_2.innerHTML = "犯我强汉,虽远必诛。" ; oDivNode_3.innerHTML = "<input type='button' value=自定义按钮>" ; oDivNode_4.innerHTML = "<a href='www.baidu.com'>超链接</a>" ; } function deleteNode(){ //获取div_1节点 var oDivNode_1 = document.getElementById("div_1"); //删除节点(较少使用) //var oRemoved = oDivNode_1.removeNode(true); //获取div_2节点 var oDivNode_2 = document.getElementById("div_2"); //获取父节点来删除节点本身 oDivNode_2.parentNode.removeChild(oDivNode_2); } function changeNode(){ //用div_3节点来替换div_1节点 var oDivNode_1 = document.getElementById("div_1"); var oDivNode_3 = document.getElementById("div_3"); //不建议使用 //oDivNode_1.replaceNode(oDivNode_3); //建议使用replaceChild() oDivNode_1.parentNode.replaceChild(oDivNode_3,oDivNode_1); } </script> <div id="div_1"> </div> <div id="div_2"> 但使龙城飞将在,不教胡马度阴山。 </div> <div id="div_3"> 骝马新跨白玉鞍,战罢沙场月色寒。 </div> <div id="div_4"> 城头铁鼓声犹振,匣里金刀血未干。 </div> </body> </html>
常见的网页效果示例
代码所处位置:
CSS:CSS代码封装在<style></style>标签中,并将其放在<head></head>中,这部分内容会先加载到内存中,增加运行速度。
javascript:javascript代码封装在<script type="text/javascript"></script>中,一般放在需要访问的位置周围即可。如果脚本要处理整个页面,那也放在<head>标签中。
新闻字体
改变新闻字体的大中小
方法一:直接在javascript代码中设置节点的属性
<html> <head> <title>新闻字体大小变化</title> <style> /*超链接访问前和访问后颜色不变*/ a:link,a:visited{ color:#00ccff; text-decoration: none; } a:HOVER { color: 0044ff; } #newstext{ width:500px; border:#00ff00 1px solid; padding:10px; } </style> </head> <body> <!-- 1,先有新闻数据,并用标签封装,这些数据可以是静态的,也可以是从数据库中拿出来的(html) 2,定义一些样式(css) 3,确定事件源和事件,以及处理方式中被处理的节点(dom) 事件源:a标签,事件:onclick,被处理的节点:div-newstext 既然要给超链接加入自定义的事件处理,就要先去掉超链接的默认效果 可以通过 href="javascript:void(0)" 来去除超链接默认效果 --> <script type="text/javascript">
//直接在javascript代码中设置节点的style属性中的各个参数,即可改变样式 function changeFont(size,clr){ //1,获取div节点对象 var oNewsText = document.getElementById("newstext"); //获取节点的是style属性 oNewsText.style.fontSize = size+"px";//数字+字符串组合成一个长字符串组,最后的+"px"可以省略
oNewsText.style.color = clr;
}
</script> <h1>女学生为买苹果手机欠高利贷 父亲要卖房还债</h1> <hr/> <a href="javascript:void(0)" onclick="changeFont('24','#0055ff')">大字体</a> <a href="javascript:void(0)" onclick="changeFont('16','#00aaff')">中字体</a> <a href="javascript:void(0)" onclick="changeFont('14','#0000ff')">小字体</a> <div id="newstext"> 今年20岁的晓玲(化名)是一名大三学生,为了买到心仪已久的苹果手机,在朋友的推荐下,晓玲开始接触网络贷款,可没想到从此晓玲陷入 了一个无底洞,如今已经欠下几十万的债务,昨天晓玲更是被追债人控制,直到父亲报警才回了家。晓玲为何会深陷高利贷的无底洞,一切还 要从2016年开始说起,刚进入大学的晓玲对外面的世界充满了好奇,为了满足自己对物质的追求,她先后贷款1万多元购买了苹果手机和电脑 </div> </body> </html>
TIPS:
在CSS代码中的属性的变量名和在DOM中的名字不一样,例如:在CSS代码中,字体大小用font-size来设置,而在DOM的div节点中的style属性中,用fontSize代表这个样式的设置
同样的,HTML标签中的属性名在DOM中也有不同的表示,例如:HTML标签中的class属性在DOM中用className表示,想要在DOM中设置HTML标签的class属性,需要设置className的值。
方法二:上面的方法要在javascript代码中直接修改属性值,万一属性值需要修改,需要修改javascript代码,不可取,所以可以在类选择器中预定义一些样式,通过修改节点的类名,就可以实现样式的切换。如果样式需要修改,只需要在CSS代码区域进行修改即可,这这里还可以将CSS代码放在css文件中,需要修改时,只需要修改css文件,连html代码都不用动,大大提高了可扩展性。
<html> <head> <title>新闻字体大小变化</title> <style> /*超链接访问前和访问后颜色不变*/ a:link,a:visited{ color:#00ccff; text-decoration: none; } a:HOVER { color: 0044ff; } #newstext{ width:500px; border:#00ff00 1px solid; padding:10px; } /*预定义一些样式,放在类选择器中,想用哪个部分的样式,只需要在javascript代码中将节点的类名改为相应的类选择器名称即可 .norm{ color:#000000; font-size:16px; background-color:cdd8d0; } .max{ color:#808080; font-size:28px; background-color:9ce9b4; } .min{ color:#ff0000; font-size:12px; background-color:f1b96d; } </style> </head> <body> <script type="text/javascript"> /* 问题:如果根据用户点击所需要的效果太多,仅通过传递多个参数来实现,虽然可以实现效果, 但是这样做,参数过多而且CSS代码和JS代码耦合性太高,不利于扩展 解决办法:先预定义一些样式,码封装到选择器中,只要根据不同的标签选择不同的选择器就可以了。 */ function changeFont2(selectorName){ var oNewsText = document.getElementById("newstext"); oNewsText.className = selectorName;//这里将节点的属性名改为了类选择器的名称。注意在DOM中,标签节点的class属性表示为className } </script> <h1>女学生为买苹果手机欠高利贷 父亲要卖房还债</h1> <hr/> <a href="javascript:void(0)" onclick="changeFont2('max')">大字体</a> <a href="javascript:void(0)" onclick="changeFont2('norm')">中字体</a> <a href="javascript:void(0)" onclick="changeFont2('min')">小字体</a> <div id="newstext" class="norm"> 今年20岁的晓玲(化名)是一名大三学生,为了买到心仪已久的苹果手机,在朋友的推荐下,晓玲开始接触网络贷款,可没想到从此晓玲陷入 了一个无底洞,如今已经欠下几十万的债务,昨天晓玲更是被追债人控制,直到父亲报警才回了家。晓玲为何会深陷高利贷的无底洞,一切还 要从2016年开始说起,刚进入大学的晓玲对外面的世界充满了好奇,为了满足自己对物质的追求,她先后贷款1万多元购买了苹果手机和电脑。 </div> </body> </html>
TIPS:导入CSS代码的时候,其中一种方法如下:
<link rel="stylesheet" type="text/css" href="cssDemo.css">
同样的,我们可以通过DOM来获取这个link节点,通过改变href属性的值,就可以改变应用到整个页面的css文件,从而改变整个页面的风格,这就是改变博客主题的原理,非常简单!!
展开闭合列表
方法一:在javascript中直接设置节点属性来实现
用到的css方法:
由于dl的默认格式是带有缩进的,所以利用组合选择器dl和dd将dd的边距设为0px,消除缩进。
要实现下级菜单列表的隐藏,将dl标签高度设为20px(一个字的高度为20px,这个值与显示屏的分辨率有关?)
overflow设置为hidden,表示超出20px的部分将会被隐藏。
用javascript代码改变overflow的值来实现下级菜单的隐藏和显示
<html> <head> <title>domDemo_List.html</title> <style type="text/css"> dl dd{ margin: 0px; } dl{ height:20px; overflow:hidden; } </style> </head> <body> <!-- 1,标签封装数据(html) 2,定义基本样式(css) 3,明确事件源,事件,要处理的节点(dom) 4,明确具体要处理的方法(js) --> <script type="text/javascript"> var flag = true; function list(){ var oDlNode = document.getElementById("list"); if(flag){ oDlNode.style.overflow = "visible"; flag = false; }else{ oDlNode.style.overflow = "hidden"; flag = true; } } </script> <dl id="list"> <dt onclick="list()">显示条目一</dt> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> </dl> </body> </html>
方法二:为了提高可扩展性,利用预定义样式来实现。
利用类选择器预定义几个样式,通过javascript来改变目标节点的类名,从而让节点获得不同的样式
<html> <head> <title>domDemo_List.html</title> <style type="text/css"> dl dd{ margin: 0px; } dl{ height:20px; } /*预定义选择器,实现动态加载*/ .open{ overflow:visible; } .close{ overflow:hidden; } </style> </head> <body> <!-- 1,标签封装数据(html) 2,定义基本样式(css) 3,明确事件源,事件,要处理的节点(dom) 4,明确具体要处理的方法(js) --> <script type="text/javascript"> function list(node){
//获取节点 var oDlNode = node.parentNode;//这个采用了另一种获取节点的方法
//设置节点的类名,匹配不同的样式 if(oDlNode.className == "open"){ oDlNode.className = "close"; }else{ oDlNode.className = "open"; } } </script> <dl class="close"> <dt onclick="list(this)">显示条目一</dt><!--this代表传入的参数是当前节点,也就是 dt节点--> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> </dl> </body> </html>
进一步改进,可以实现多个列表的(只能在IE6上实现,谷歌和IE7以后的为什么不行?)
<html> <head> <title>domDemo_List.html</title> <style type="text/css"> dl dd{ margin: 0px; } dl{ height:20px; } /*预定义选择器,实现动态加载*/ .open{ overflow:visible; } .close{ overflow:hidden; } </style> </head> <body> <!-- 1,标签封装数据(html) 2,定义基本样式(css) 3,明确事件源,事件,要处理的节点(dom) 4,明确具体要处理的方法(js) --> <script type="text/javascript"> function list(node){ //获取节点 var oDlNode = node.parentNode;//这个采用了另一种获取节点的方法 //设置节点的类名,匹配不同的样式 if(oDlNode.className == "open"){ oDlNode.className = "close"; }else{ oDlNode.className = "open"; } } </script> <dl class="close"> <dt onclick="list(this)">显示条目一</dt><!--this代表传入的参数是当前节点,也就是 dt节点--> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> </dl> <dl class="close"> <dt onclick="list(this)">显示条目一</dt><!--this代表传入的参数是当前节点,也就是 dt节点--> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> <dd>展开列表内容</dd> </dl> </body> </html>
接下来实现 一次只展开多个列表中的一个(只在IE6实现)
思路:遍历所有的dl,只对当前节点执行展开操作,其他节点全部执行关闭操作。
TIPS:判断两个DOM节点是否相同,可以用==来做。
<html> <head> <title>domDemo_List.html</title> <style type="text/css"> dl dd{ margin: 0px; } dl{ height:20px; } /*预定义选择器,实现动态加载*/ .open{ overflow:visible; } .close{ overflow:hidden; } </style> </head> <body> <!-- 1,标签封装数据(html) 2,定义基本样式(css) 3,明确事件源,事件,要处理的节点(dom) 4,明确具体要处理的方法(js) --> <script type="text/javascript"> function list(node){ //获取当前节点 var oDlNode = node.parentNode; //获取所有dl节点 var collDlNodes = document.getElementsByTagName("dl");
//遍历节点,是当前节点,就打开,不是当前节点,就关闭 for(var x = 0;x<collDlNodes.length;x++){ if(collDlNodes[x] == oDlNode){//这里的判断可以直接用==来进行 if(oDlNode.className == "open"){ oDlNode.className = "close"; }else{ oDlNode.className = "open"; } }else{ collDlNodes[x].className = "close"; } } } </script> <dl class="close"> <dt onclick="list(this)">显示条目一</dt> <dd>展开列表内容1</dd> <dd>展开列表内容1</dd> <dd>展开列表内容1</dd> <dd>展开列表内容1</dd> </dl> <dl class="close"> <dt onclick="list(this)">显示条目二</dt> <dd>展开列表内容2</dd> <dd>展开列表内容2</dd> <dd>展开列表内容2</dd> <dd>展开列表内容2</dd> </dl> <dl class="close"> <dt onclick="list(this)">显示条目三</dt> <dd>展开列表内容3</dd> <dd>展开列表内容3</dd> <dd>展开列表内容3</dd> <dd>展开列表内容3</dd> </dl> </body> </html>
好友列表的实现
主要逻辑用javascript,如果精通CSS,也可以用纯css代码来实现。
好友列表基本实现
<html> <head> <title>friendList.html</title> <style type="text/css"> table ul{ background-color:#26e356; list-style:none;/*去除无序列表的点*/ margin:0px; /*外边距取消*/ display:none; } table{ border:1px solid #00ccff; width:120px; } table td{ background-color:#f3c98f; border:1px solid #00ccff; } /*单元格中的超链接样式*/ table td a:link,table td a:visited{ color:#1f6df1; text-decoration:none; } /*预定义表格的显示方式*/ .open{ display:block; } .close{ display:none; } </style> </head> <body> <!-- 好友菜单实现效果,而且要求一次这打开一个 --> <script type="text/javascript"> function list(node){ //获取被操作的节点ul,通过超链接标签的父节点来获取ul标签,不用兄弟节点 var oTdNode = node.parentNode; var oUlNode = oTdNode.getElementsByTagName("ul")[0]; //alert(oUlNode.nodeName); if(oUlNode.className =="open"){ oUlNode.className = "close"; }else{ oUlNode.className = "open"; } } </script> <table id="friendList"> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> </table> </body> </html>
好友列表实现,且一次只打开一个列表
CSS的display属性
display:none 代表该区域隐藏。
display:block 代表区域显示,长度不够自动换行。
padding 代表内边距。
<html> <head> <title>friendList.html</title> <style type="text/css"> table ul{ background-color:#26e356; list-style:none;/*去除无序列表的点*/ margin:0px; /*外边距取消*/ display:none; padding:0px;/*这一条是针对谷歌浏览器的*/ } table{ border:1px solid #00ccff; width:120px; } table td{ background-color:#f3c98f; border:1px solid #00ccff; } /*单元格中的超链接样式*/ table td a:link,table td a:visited{ color:#1f6df1; text-decoration:none; } /*预定义表格的显示方式*/ .open{ display:block; } .close{ display:none; } </style> </head> <body> <!-- 好友菜单实现效果,而且要求一次这打开一个 --> <script type="text/javascript"> function list(node){ //获取被操作的节点ul,通过超链接标签的父节点来获取ul标签,不用兄弟节点 var oTdNode = node.parentNode; var oUlNode = oTdNode.getElementsByTagName("ul")[0]; //获取所有节点 var oTabNode = document.getElementById("friendList"); var collUlNodes = oTabNode.getElementsByTagName("ul"); for(var x = 0 ;x<collUlNodes.length;x++){ if(collUlNodes[x] == oUlNode){ if(oUlNode.className =="open"){ oUlNode.className = "close"; }else{ oUlNode.className = "open"; } }else{ collUlNodes[x].className = "close"; } } } </script> <table id="friendList"> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> <tr> <td> <a href="javascript:void(0)" onclick="list(this)">好友菜单</a> <ul> <li>一个好友</li> <li>一个好友</li> <li>一个好友</li> </ul> </td> </tr> </table> </body> </html>
表格
下拉菜单
表单校验
主要是为了防止用户误输入,所以现在前端进行检验,这样就能减轻后端的校验压力。但是,后端也必须进行校验,因为传输过程中也有可能发生错误。
1,校验的最基本流程
当输入的是abc时,显示合法,不是abc时,显示用户名错误。
onblur事件:在光标脱离输入框时,就会触发该事件
<html> <head> <title>dataTest.html</title> </head> <body> <script type="text/javascript"> //校验用户名 function checkUser(){ var oUserNode = document.getElementsByName("user")[0]; var oSpanNode = document.getElementById("userSpan"); var name = oUserNode.value; if(name == "abc"){ oSpanNode.innerHTML = "<font color='green' size='2px'>合法!</font>"; }else{ oSpanNode.innerHTML = "用户名输入有误!".fontcolor("red"); } } </script> <form> 用户名:<input type="text" name="user" onblur="checkUser()"/> <span id="userSpan"></span><br/> 输入密码:<input type="text" name=pwd /> </form> </body> </html>
2,利用正则表达式进行字符串格式的判断
javascript中的正则表达式对象的两种创建方法:
var reg = new RegExp("[a-z]{4}","i");//第一个参数为正则表达式模式,i代表不区分大小写,m代表多行查找,g代表全文查找出现的所有模式
var reg = /[a-z]{4}/
两种方式的区别:在第一种方法中,由于正则表达式是写在双引号中的,所以要考虑转移字符的问题,如:\d 如果出现在第一种中。需要写成 \\d ,而第二种可以直接写
关于表达式模式
[a-z]{4}:四个连续的英文字母,11abcd这种情况也满足要求的
^[a-z]{4}$:加上头尾的限定,^表示字符串的头,$表示字符串的尾,这个表达式的含义是字符串的从头到尾有4个连续的英文字母
^[0-9]{4}$:加上头尾的限定,^表示字符串的头,$表示字符串的尾,这个表达式的含义是字符串的从头到尾有4个连续的数字, [0-9] 也可以写作 \d,用第一种方法创建的时候,需要转义。
两种使用正则表达式校验数据格式的方法:
字符串的match方法:使用正则表达式方法对字符串进行查找,并将包含查找的结果作为数组返回。
用法:stringObj.match(RegExp);
或者用正则表达式对象的test方法:指出在被查找的字符串中是否存在模式,返回boolean。
用法:reg.test(str);
<script type="text/javascript"> //校验用户名 function checkUser(){ var oUserNode = document.getElementsByName("user")[0]; var oSpanNode = document.getElementById("userSpan"); var name = oUserNode.value; //定义正则表达式 var reg = new RegExp("^[a-z]{4}$","i");// ^表示字符串的头,$表示字符串的尾,这个表达式的含义是字符串的从头到尾有四个连续的字母 if(reg.test(name)){ oSpanNode.innerHTML = "<font color='green' size='2px'>合法!</font>"; }else{ oSpanNode.innerHTML = "用户名输入有误!".fontcolor("red"); } } </script>
3,数据校验完成之后,接下来就是进行提交,数据提交有两种方法
第一种是用form表单中的submit按钮,
<form> 用户名:<input type="text" name="user" onblur="checkUser()"/> 输入密码:<input type="text" name=pwd /> <input type="submit" value="提交数据" /> </form>
第二种是用DOM方法,form表单节点中的submit方法,只要获取到form的DOM节点,就可以通过某个按钮来触发javascript函数,来实现提交。同样的也可以用超链接来触发提交。
<script type="text/javascript"> function mySubmit(){ var oFormNode = document.getElementById("userInfo"); oFormNode.submit(); } </script> <form id="userInfo"> 用户名:<input type="text" name="user" onblur="checkUser()"/> <span id="userSpan"></span><br/> 输入密码:<input type="text" name=pwd /> <span id="pwdSpan"></span><br/> </form> <input type="button" value="我的提交" onclick="mySubmit()" />
4,表单数据可以提交的前提是用户输入的所有数据都是符合格式要求的,那么怎么在提交之前获取数据校验的结果呢?
<form>表单有默认的提交动作,即在你点击form中的提交按钮之后,form表单中的数据会直接提交到服务器,在这里需要更改默认动作,来实现自己对提交过程的控制。
例如,如果改为 <form onsubmit="return false"> ,现在点击提交按钮,不会有任何反应。
如果改为 <form onsubmit="return check()"> ,check() 函数的返回结果将会决定是否提交。所以我可以用check函数来判断数据的校验情况。
为了便于判断,在每个数据的判断之后,需要一个标志位来标识数据的输入情况。
<html> <head> <title>dataTest.html</title> </head> <body> <script type="text/javascript"> //校验用户名 function checkUser(){ var flag; var oUserNode = document.getElementsByName("user")[0]; var oSpanNode = document.getElementById("userSpan"); var name = oUserNode.value; //定义正则表达式 var reg = new RegExp("^[a-z]{4}$","i");// ^表示字符串的头,$表示字符串的尾,这个表达式的含义是字符串的从头到尾有四个连续的字符串 if(reg.test(name)){ oSpanNode.innerHTML = "<font color='green' size='2px'>合法!</font>"; flag = true; }else{ oSpanNode.innerHTML = "用户名输入有误!".fontcolor("red"); flag = false; } return flag; } function checkForm(){ if(checkUser()) return true; return false; } function mySubmit(){ var oFormNode = document.getElementById("userInfo"); oFormNode.submit(); } </script> <form onsubmit="return checkForm()"> 用户名:<input type="text" name="user" onblur="checkUser()"/> <span id="userSpan"></span><br/> 输入密码:<input type="text" name=pwd /> <span id="pwdSpan"></span><br/> <input type="submit" value="提交数据" /> </form> </body> </html>
5,完整校验过程
上面这就已经能够完成数据的校验,但是这个方法只校验了一个数据,如果一个表单中有许多数据要校验,上面的方法代码重复率太高了,需要进行抽取。
下面是完整的校验过程,用户名:五个连续的英文字母,密码:五个连续的数字,邮箱:1@1.com
<html> <head> <title>dataTest.html</title> </head> <body> <script type="text/javascript"> //校验用户名 function check(name,reg,spanId,okInfo,errorInfo){ var flag; var val = document.getElementsByName(name)[0].value; var oSpanNode = document.getElementById(spanId); //定义正则表达式 if(reg.test(val)){ oSpanNode.innerHTML = okInfo.fontcolor("green"); flag = true; }else{ oSpanNode.innerHTML = errorInfo.fontcolor("red"); flag = false; } return flag; } //校验用户名 function checkUser(){ var reg = /^[a-z]{5}$/i; return check("user",reg,"userSpan","用户名正确","用户名错误") } //校验密码 function checkPwd(){ var reg = /^[0-9]{5}$/; return check("pwd",reg,"pwdSpan","密码格式正确","密码格式错误") } //校验重输密码,只要和密码一致即可 function checkRePwd(){ var flag; //获取密码框内容 var pass = document.getElementsByName("pwd")[0].value; //获取确认密码框内容 var rePass = document.getElementsByName("rePwd")[0].value; //获取确认密码的span区域 var oSpanNode = document.getElementById("rePwdSpan"); if(pass == rePass){ oSpanNode.innerHTML = "两次密码一致".fontcolor("green"); flag = true; }else{ oSpanNode.innerHTML = "两次密码不一致".fontcolor("red"); flag = false; } return flag; } //校验邮件 function checkMail(){ var reg = /^\w+@\w+(\.\w+)+$/i; return check("mail",reg,"mailSpan","邮件格式正确","邮件格式错误") } //判断是否可以提交 function checkForm(){ alert(checkUser() +"--"+ checkPwd() +"--"+ checkRePwd() +"--"+ checkMail()) if(checkUser() && checkPwd() && checkRePwd() && checkMail()) return true; return false; } </script> <form onsubmit="return checkForm()"> 用户名:<input type="text" name="user" onblur="checkUser()"/> <span id="userSpan"></span><br/> 输入密码:<input type="text" name=pwd onblur="checkPwd()" /> <span id="pwdSpan"></span><br/> 确认密码:<input type="text" name=rePwd onblur="checkRePwd()"/> <span id="rePwdSpan"></span><br/> 邮件地址:<input type="text" name=mail onblur="checkMail()"/> <span id="mailSpan"></span><br/> <input type="submit" value="提交数据" /> </form> </body> </html>
待续。。。。。