0.升级tab栏切换
在上一节中写了单一的一个容器里面tab切换的示例,在实际开发中往往都是多个容器里的多个tab互相切换,例如淘宝首页的几楼都是这样,本节先升级一下上节的示例,鼠标滑过时选中tab,如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95<head>
<meta charset="UTF-8">
<title>01tab栏切换升级版</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 300px;
height: 300px;
border:1px solid #ccc;
margin: 50px auto;
overflow: hidden;
}
ul{
list-style-type: none;
}
.top span{
display: inline-block;
background-color: pink;
width: 70px;
height: 30px;
line-height: 30px;
text-align: center;
cursor:pointer;
}
.top span.current{
background-color: purple;
}
.bottom li{
width: 100%;
height: 270px;
background-color: purple;
display: none;
}
.bottom li.show{
display: block;
}
</style>
<script>
window.onload = function(){
//获取所有的span和li(这里需要指出的是span和li必须是一一对应的,即个数必须得相等)
var spans = document.getElementsByTagName("span");
var lis = document.getElementsByTagName("li");
for(var i=0;i<spans.length;i++){
spans[i].index = i; //给span设置index属性,先存下下标,关键
spans[i].onmouseover = function(){
//清除所有的li和span的属性(排他思想)
for(var j=0;j<spans.length;j++){
spans[j].className="";
lis[j].className="";
}
//选中点击的span和它对应的li
this.className="current";
lis[this.index].className="show";
}
}
}
</script>
</head>
<body>
<div class="box">
<div class="top">
<span class="current">新闻</span>
<span>体育</span>
<span>娱乐</span>
<span>八卦</span>
</div>
<div class="bottom">
<ul>
<li class="show">新闻模块</li>
<li>体育模块</li>
<li>娱乐模块</li>
<li>八卦模块</li>
</ul>
</div>
</div>
<div class="box">
<div class="top">
<span class="current">新闻</span>
<span>体育</span>
<span>娱乐</span>
<span>八卦</span>
</div>
<div class="bottom">
<ul>
<li class="show">新闻模块</li>
<li>体育模块</li>
<li>娱乐模块</li>
<li>八卦模块</li>
</ul>
</div>
</div>
</body>
1.循环语句
js(以及大多数其它语言)都会有for循环,while循环,do while循环。
- for循环:for(初始化;条件;增量){ //执行语句}
- while循环:while(条件){ //执行语句}
- do while循环:do{ //执行语句} while(条件);
由以上可知,do while循环至少会执行一次语句(因为先执行才判断条件是否成立),三个循环不是太难,这里不再举例。2.switch分支语句
switch是从多个条件中选择一个匹配的去执行,跟if elseif的作用是一样的,但是效率的话switch更高。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38<head>
<meta charset="UTF-8">
<title>02switch语句</title>
<style>
body{
background: url(images/chun1.jpg) no-repeat;
}
</style>
<script>
window.onload = function(){
var sel = document.getElementById("sel");
sel.onchange = function(){
switch(this.value){
case "1":
document.body.style.backgroundImage = "url(images/chun1.jpg)";
break;
case "2":
document.body.style.backgroundImage = "url(images/xia1.jpg)";
break;
case "3":
document.body.style.backgroundImage = "url(images/qiu1.jpg)";
break;
case "4":
document.body.style.backgroundImage = "url(images/dong1.jpg)";
break;
}
}
}
</script>
</head>
<body>
<select name="" id="sel">
<option value="1">春意盎然</option>
<option value="2">夏日炎炎</option>
<option value="3">秋声瑟瑟</option>
<option value="4">冬雪皑皑</option>
</select>
</body>
这里根据不同的下拉选框,换不同的北京图片。onchange可以监听下拉改变事件,当当前选定的值匹配到1,2,3,4是执行对应的case语句,执行完毕之后需要break(字面意思打断)停止当前代码继续向下执行。可以使用backgroundImage属性来修改背景图片,如果是链接用url,路径不要加引号。
3.数组常用方法
3.1添加数组元素
- push() 从数组后面追加元素
使用push()方法可向数组末尾添加一个或多个元素,并返回数组新的长度。例如:
var arr = [“张三”,”李四”]; var length = arr.push(“王五”); 则执行结果是length=3,arr=[“张三”,”李四”,”王五”]; - unshift() 从数组前面添加元素
使用unshift()方法可在数组开头添加一个或多个元素,并返回数组新的长度。例如:
var arr = [“张三”,”李四”]; var length = arr.push(“王五”); 则执行结果是length=3,arr=[“王五”,张三”,”李四”];3.2删除数组元素
- pop() 删除数组最后一个元素,并返回最后一个元素的值
如var arr=[1,3,5],var a = arr.pop(),执行完毕a=5,arr=[1,3]; - shift() 删除数组第一个元素,并返回第一个元素的值
如var arr=[1,3,5],var a = arr.shift(),执行完毕a=1,arr=[3,5];3.3连接数组元素
- concat() 连接两个或多个数组
使用concat()可以连接两个或多个数组,它不会修改当前的数组,只会返回一个连接后的新的数组
var a=[1,2,3]; var b = [‘a’,’b’,’c’]; var c = a.concat(b);连接之后数组a,b都不会改变,c=[1,2,3,’a’,’b’,’c’];3.4把数组中的元素连接成字符串
- join() 使用分隔符将数组中的元素连接成字符串
使用join(‘分隔符’)函数可将数组中的元素通过分隔符连接成一个字符串,分隔符可以为空,为空时默认分隔符都逗号。
如var arr = [1,2,3]; 则var str = arr.join(‘-‘); str的结果就是1-2-3.3.5把字符串分割成数组
- split() 使用分隔符将字符串分割成数组。这个其实就是上面方法的逆运算
使用split(‘分隔符’,’数组长度’)函数可以将字符串按照分隔符分割成数组,其中分隔符和数组长度都可以省略,分隔符省略时默认是逗号。
如:var str = aa-bb-cc; var arr = str.split(“-“); 则arr数组的值为[aa,bb,cc].4.DOM操作
js是由ECMAScript(欧洲计算机协会,负责描述了js的基本语法和对象),DOM(Document Object Model文档对象模型,负责处理网页内容)对象和BOM(Borwser Object Model浏览器对象模型,负责处理与浏览器交互)对象组成。
在这里我们主要介绍DOM,DOM为文档提供了结构化的描述,其实就是定义了如何通过脚本来访问文档结构(说白了就是怎么使用js操作html元素)。4.1节点
整个html文档是个文档节点;
每个html标签是个元素节点;
标签中的文字是文字节点;
标签的属性是属性节点;
在html中一切皆是节点。4.2访问节点
getElementById(); 根据id访问节点;
getElementsByTagName(); 根据标签名访问节点;
getElementsByClassName((); 根据类名访问节点,但是这个方法存在兼容问题,对于IE6/7/8不支持,我们可以封装自己的方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51<head>
<meta charset="UTF-8">
<title>03封装class类</title>
<style>
div{
width: 50px;
height: 50px;
margin: 10px;
background: pink;
}
</style>
<script>
window.onload = function(){
//封装我们自己的根据类名获取元素的方法
function getByClass(classname){
//判断是否支持js原生方法(即区分IE678和其它浏览器)
if(document.getElementsByClassName){
return document.getElementsByClassName(classname);
}
//程序走到这里,说明不支持document.getElementsByClassName方法,获取全部节点,遍历判断
var arr = []; //定义返回数组
var elems = document.getElementsByTagName("*"); //获取页面所有节点
for(var i=0;i<elems.length;i++){
//获取这个元素的class类,并使用空格分割(比如demo test,不分割单纯的判断会有问题)
var classes = elems[i].className.split(" ");
for(var j=0;j<classes.length;j++){
if(classes[j]==classname){
//存在此类名,将元素放入数组中
arr.push(elems[i]);
}
}
}
return arr;
}
//调用
var tests = getByClass("test");
for(var k=0;k<tests.length;k++){
tests[k].style.backgroundColor="red"; //结果就是两个变红,IE678测试没有问题
}
}
</script>
</head>
<body>
<div></div>
<div class="demo"></div>
<div></div>
<div class="demo test"></div>
<div></div>
<div class="test one"></div>
<div></div>
</body>
思路:根据getElementsByClassName判断是高级浏览器还是IE6/7/8,如果是高级浏览器则直接根据此方法返回,如果是IE6/7/8则遍历所有节点,再根据节点,获取节点里面的类,因为一个节点可能有多个类属性,中间是空格(比如demo test),所以再用空格分割,看是否包含这个类名,如果有则把当前节点(不是类名)放入数组中,最后返回。
4.3创建节点
使用creatElement()方法可以创建节点。
如:var div = document.creatElement(“div”);就生成了一个div标签。
4.4插入节点
- appendChild(); 添加子节点( 字面意思添加孩子),放到盒子最后面。
- insertBefore(插入的节点,参照节点) 在参照节点之前插入节点,如果第二个参数不写则在盒子最后添加节点。
如:demo.insertBefore(test,childrens[0]); 在第一个孩子元素之前添加节点test。
demo.insertBefore(test,null);在盒子最后添加节点test。4.5删除节点
removeChild() 删除孩子节点
demo.removeChild(aa); 从demo节点移除孩子节点aa。4.6克隆(复制)节点
cloneNode() 复制节点
括号里面可以跟参数,如果里面是true,则是深复制,除了复制盒子本身,还复制盒子子节点 ;如果是false则是浅复制,只复制该节点,不复制子节点。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<body>
<div id="demo">
<div id="one"></div>
<div id="two"></div>
</div>
<script>
var demo = document.getElementById("demo");
var one = document.getElementById("one");
//创建节点
var three = document.createElement("div");
//在后面添加节点
demo.appendChild(three);
//在前面插入节点
demo.insertBefore(three,null);
//删除节点
demo.removeChild(one);
//深克隆节点
var cloneNode = demo.cloneNode(true);
//克隆完要追加才能看到
demo.parentNode.appendChild(cloneNode);
</script>
</body>
5.布尔类型的真假
数据类型 | 真假 |
---|---|
数字类型 | 除0之外所有数字均为真,0是假 |
字符串 | 所有字符串都是真,’’是假 |
对象 | 所有对象均为真,null是假 |
undefined | Undefined类型只有undefined,是假 |
6.访问关系(重点)
js中的访问关系有四种
- 父节点
parentNode - 兄弟节点
nextSibling、nextElementSlibling、previousSibling、previousElementSibling - 子节点
firstChild、firstElementChild、lastChild、lastElementChild - 所有子节点
childNodes、children6.1父节点
parentNode获取到的是元素的直接父节点(不包括爷爷),只有一个。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38<head>
<meta charset="UTF-8">
<title>06二维码</title>
<style>
.box{
width:107px;
margin: 100px auto;
position: relative;
border: 1px solid #cccccc;
}
#close{
width: 14px;
height: 14px;
font-size: 14px;
position: absolute;
line-height: 14px;
top:0;
left:-15px;
border: 1px;
cursor:pointer;
display: block;
}
</style>
<script>
window.onload = function(){
var close = document.getElementById("close");
close.onclick = function(){
this.parentNode.style.display = "none";
}
}
</script>
</head>
<body>
<div class="box">
<img src="images/taobao.jpg">
<span id="close">x</span>
</div>
</body>
这个例子中当点击叉号时关闭页面,用到了parentNode,布局采用”子绝父相“,点击按钮时,根据当前节点,让它的父节点的display属性改为none即为隐藏。
6.2兄弟节点
- nextSibling 下一个兄弟节点(不是所有的兄弟节点,只是当前节点的下一个兄弟),IE6/7/8使用
- nextElementSibling 跟上面意思一样,供高版本浏览器使用的。
- previousSibling下一个兄弟节点(不是所有的兄弟节点,只是当前节点的下一个兄弟),IE6/7/8使用
- previousElementSibling 跟上面意思一样,供高版本浏览器使用的。
基于以上的特点,我们在平时开发中一般用或(||)连接在一块使用,保证在IE6/7/8和高版本浏览器都是可用的。如:var div = one.nextElementSibling || one.nextSibling; 而且必须是高版本浏览器的在前,IE6/7/8的在后。6.3子节点
- firstChild 第一个孩子节点,IE6/7/8使用
- firstElementChild 第一个孩子节点,供高版本浏览器使用的。
- lastChild 最后一个孩子节点,IE6/7/8使用(IE6/7/8大坑!!)
- previousElementSibling 最后一个孩子节点,供高版本浏览器使用的。
为保证兼容可以这样使用:var div = one.firstElementChild || one.firstChild;6.4孩子节点
- childNodes 选出全部的孩子节点(亲的)。这个是js官方的,但是不太好用,因为在高版本浏览器中,会把换行也当做节点,还需要再根据nodeType判断一次(nodeType =1是元素节点)。
- children 选出所有的孩子节点(只有元素)。这个是民间大神弄的,但是更好用,一般使用这个。
需要注意一点的是,在IE678中会把注释也当做节点,计算节点个数的时候往往比正常浏览器多,避免的方法就是在要使用的元素代码里面不要写注释(第一次推荐不写注释)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<head>
<meta charset="UTF-8">
<title>孩子节点</title>
<script>
window.onload = function(){
var father = document.getElementsByTagName("ul")[0];
//如果使用第二种就不用判断了,方便alert(father.children.length);
var cs = father.childNodes;
for(var i=0;i<cs.length;i++){
if(cs[i].nodeType==1){
//不加nodeType判断,在高版本浏览器会报错
cs[i].style.backgroundColor = "pink";
}
}
}
</script>
</head>
<body>
<div>
<ul>
<li>123</li>
<li>123</li>
<li>123</li>
</ul>
</div>
</body>