前端入门—js第四天

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、children

    6.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>

代码地址:https://git.oschina.net/catchu/web-study

刘俊重 wechat
欢迎关注我的微信公众号
坚持原创技术分享