P127. 定时器简介

这节课将实现制作一个简易的定时器。

setInterval()

  • 这个方法可以对函数定时调用,将一个函数每隔一段时间执行一次。
  • 参数:
      1. 回调函数,该函数会每隔一段时间执行一次。
      1. 每次调用间隔的时间,单位为毫秒。
  • 有一个返回值:
    • 返回一个Number类型的数据。
    • 这个数字用来作为定时器的唯一标识,方便我们用clearInterval()关闭定时器。

clearInterval()

  • 可以用来关闭一个定时器。
  • 方法中需要一个定时器的标识符作为参数。

下面就可以实现定时器的功能了。

  1. ...
  2. <script type="text/javascript">
  3. window.onload = function(){
  4. var content = document.querySelector("#content");
  5. var num = 1;
  6. //设置定时器
  7. var timer = setInterval(function(){
  8. content.innerHTML = num++;
  9. if (num == 100) { clearInterval(timer); } //当num为100时结束定时器
  10. },50);
  11. }
  12. </script>
  13. ...
  14. <body>
  15. <h2 id="content">1</h2>
  16. </body>
  17. ...

P128. 切换图片练习

本节课将实现一个自动切换图片的练习。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript">
  9. window.onload = function(){
  10. var img = document.querySelector("#img1");
  11. var imgArr = ["../images/01.jpg","../images/02.jpg","../images/03.jpg","../images/04.jpg"]
  12. var index = 0;
  13. setInterval(function(){
  14. index++;
  15. //下面这行代码和18行代码同样作用,却更简洁。
  16. //因为当索引超过数组的时候需要重置索引,4%4刚好又为0
  17. index = index % imgArr.length;
  18. // if (index >= imgArr.length){ index = 0; }
  19. img.src = imgArr[index];
  20. },500);
  21. };
  22. </script>
  23. </head>
  24. <body>
  25. <img src="../images/01.jpg" id="img1" width="300px" height="300px"/>
  26. </body>
  27. </html>

我们还希望可以为我们的网页添加两个按钮,我们点击开始的时候开始,点击停止的时候停止。这其实也很简单,为我们的定时器绑定单击响应函数即可。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript">
  9. window.onload = function(){
  10. var img = document.querySelector("#img1");
  11. var imgArr = ["../images/01.jpg","../images/02.jpg","../images/03.jpg","../images/04.jpg"]
  12. var index = 0;
  13. var start = document.querySelector("#start");
  14. var stop = document.querySelector("#stop");
  15. var timer; //这里的timer一定要是全局变量,不然stop()读取不到timer。
  16. start.onclick = function(){
  17. //一定要在开始位置清空一次定时器,不然当你多次点击定时器时
  18. //会重复执行多个定时器,导致图片切换速度变快。
  19. clearInterval(timer);
  20. timer = setInterval(function(){
  21. index++;
  22. index = index % imgArr.length;
  23. img.src = imgArr[index];
  24. },500);
  25. };
  26. stop.onclick = function(){
  27. clearInterval(timer);
  28. }
  29. };
  30. </script>
  31. </head>
  32. <body>
  33. <img src="../images/01.jpg" id="img1" width="300px" height="300px"/>
  34. </br></br>
  35. <button id="start">开始</button> //点击开始开始定时器
  36. <button id="stop">停止</button> //点击停止关闭定时器
  37. </body>
  38. </html>

好的,那么做到这里,我们的程序就暂时做完了,当然,现在程序还不够完善,如果有能力的朋友可以想办法再改进改进这些代码。
还记得前面学习事件的时候(P123)使用键盘移动div那一课吗?我们最后面制作出的程序发现,由于因为键盘为了防误操作设计,第一次移动div总是有停顿感,我们现在学了定时器,有什么方法可以改进呢?


P129. 改进键盘移动div练习

我们前面制作的代码,我们发现,移动方向是没有问题的,有问题的是移动的速度,我们发现我们的控制方向和控制速度都是在onkeydown事件中完成的,这是不好的,就像我们骑自行车一样,手用来管方向,而脚用来管速度。
所以我们可以开启一个定时器,来控制div移动的速度。
代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style type="text/css">
  9. #box1{
  10. width: 100px;
  11. height: 100px;
  12. background-color: red;
  13. position: absolute;
  14. }
  15. </style>
  16. <script type="text/javascript">
  17. window.onload = function(){
  18. var speed = 20; //定义初始速度
  19. dir = 0; //初始化方向为0
  20. var box1 = document.querySelector("#box1");
  21. setInterval(function(){
  22. switch(dir){
  23. case 38:
  24. box1.style.top = box1.offsetTop - speed + "px";
  25. break;
  26. case 40:
  27. box1.style.top = box1.offsetTop + speed + "px";
  28. break;
  29. case 37:
  30. box1.style.left = box1.offsetLeft - speed + "px";
  31. break;
  32. case 39:
  33. box1.style.left = box1.offsetLeft + speed + "px";
  34. break;
  35. }
  36. },10);
  37. document.onkeydown = function(event){
  38. //上:38 下:40 左:37 右:39
  39. if (event.ctrlKey){
  40. speed = 50; //按ctrl加速。
  41. }
  42. else{
  43. speed = 10;
  44. }
  45. // dir等于键盘的上下左右按键
  46. dir = event.keyCode;
  47. }
  48. document.onkeyup = function(){
  49. // 松手需要把dir设置为0,这样才会停止switch事件
  50. dir = 0;
  51. }
  52. }
  53. </script>
  54. </head>
  55. <body>
  56. <div id="box1"></div>
  57. </body>
  58. </html>

P130. 延时调用

延时调用:

  • 使用setTimeout()方法。
  • 延时调用的函数不马上执行,而是隔一段时间后执行,而且只执行一次。
  • 延时调用和定时调用的区别,定时调用会执行多次,延时调用只执行一次。
  • 语法:setTimeout(回调函数,延时时间)

关闭延时调用:

  • 使用clearTimeout()方法。
  • 和关闭定时器方法一样使用。
  • 语法:clearTimeout(延时器名字)

使用方法如:

  1. var num = 1;
  2. //设置延时器
  3. var timer = setTimeout(function(){
  4. console.log(num++);
  5. },3000)
  6. //关闭延时器
  7. clearInterval(timer);

P131. 定时器的应用(一)

本节课我们利用定时器制作一个点击按钮向右移动div的效果,并且div移动到页面800像素的位置会自动停下来。

代码清单:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style type="text/css">
  9. *{
  10. padding: 0;
  11. margin: 0;
  12. }
  13. #box1{
  14. width: 100px;
  15. height: 100px;
  16. background-color: red;
  17. position: absolute;
  18. left:0;
  19. }
  20. #box2{
  21. width: 0px;
  22. border-right: 1px solid black;
  23. height: 1000px;
  24. background-color: black;
  25. position: absolute;
  26. top: 0px;
  27. left: 800px;
  28. }
  29. </style>
  30. <script type="text/javascript">
  31. window.onload = function(){
  32. var btn = document.querySelector("#btn");
  33. var box1 = document.querySelector("#box1");
  34. var timer;
  35. //点击按钮以后,box向右移动
  36. btn.onclick = function(){
  37. //每次点击按钮重置定时器
  38. clearInterval(timer);
  39. //开启定时器,执行移动效果
  40. timer = setInterval(function(){
  41. //利用parseInt()方法,过滤掉字符串中的px字符,也可以使用正则表达式
  42. var oldLeft = parseInt(getStyle(box1,"left"));
  43. var newLeft = oldLeft + 12;
  44. if (newLeft > 800){
  45. newLeft = 800;
  46. }
  47. box1.style.left = newLeft + "px";
  48. if (newLeft === 800){
  49. //达到目标线,停止定时器
  50. clearInterval(timer);
  51. }
  52. },20);
  53. };
  54. function getStyle(obj,str){
  55. //利用或运算的优势,style等于网页中有的那个方法。
  56. style = obj.currentStyle || window.getComputedStyle(obj,null);
  57. return style[str];
  58. }
  59. };
  60. </script>
  61. </head>
  62. <body>
  63. <button id="btn">点击按钮向右移动div</button>
  64. </br></br>
  65. <div id="box1"></div>
  66. <div id="box2"></div>
  67. </body>
  68. </html>

P132. 定时器的应用(二)

上节课的代码虽然已经可以实现功能,但是还不够完善,这节课我们将尝试添加一个向左移动div的按钮,并将代码封装到一个函数中。

函数参数提示:

  • obj:需要执行移动效果的对象。
  • target:执行动画的目标位置。
  • speed:移动的速度(正数向右移动,负数向左移动)

代码清单:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style type="text/css">
  9. *{
  10. padding: 0;
  11. margin: 0;
  12. }
  13. #box1{
  14. width: 100px;
  15. height: 100px;
  16. background-color: red;
  17. position: absolute;
  18. left:0;
  19. }
  20. #box2{
  21. width: 0px;
  22. border-right: 1px solid black;
  23. height: 1000px;
  24. background-color: black;
  25. position: absolute;
  26. top: 0px;
  27. left: 800px;
  28. }
  29. </style>
  30. <script type="text/javascript">
  31. window.onload = function(){
  32. var btn1 = document.querySelector("#btn1");
  33. var btn2 = document.querySelector("#btn2");
  34. var box1 = document.querySelector("#box1");
  35. btn1.onclick = function(){
  36. move(box1,800,10);
  37. };
  38. btn2.onclick = function(){
  39. move(box1,0,10);
  40. };
  41. };
  42. function getStyle(obj,str){
  43. //利用或运算的优势,style等于网页中有的那个方法。
  44. style = obj.currentStyle || window.getComputedStyle(obj,null);
  45. return style[str];
  46. }
  47. var timer;
  48. function move(obj,target,speed){
  49. clearInterval(timer);
  50. //获取元素当前的位置
  51. var current = parseInt(getStyle(obj,"left"));
  52. //判断速度的正负值,如果0像800移动,speed为正,如果800向0移动,speed为负
  53. if (current > target){
  54. speed = -speed;
  55. }
  56. timer = setInterval(function(){
  57. var oldLeft = parseInt(getStyle(obj,"left"));
  58. var newLeft = oldLeft + speed;
  59. //利用speed正负判断方向
  60. //向右移动时,需要判断newLeft是否大于target
  61. //向左移动时,需要判断newLeft是否小于target
  62. if ((speed < 0 && newLeft < target) || (speed > 0 && newLeft > target)){
  63. newLeft = target;
  64. }
  65. obj.style.left = newLeft + "px";
  66. if (newLeft === target){
  67. //达到目标线,停止定时器
  68. clearInterval(timer);
  69. }
  70. },20);
  71. }
  72. </script>
  73. </head>
  74. <body>
  75. <button id="btn1">点击按钮向右移动div</button>
  76. <button id="btn2">点击按钮向左移动div</button>
  77. </br></br>
  78. <div id="box1"></div>
  79. <div id="box2"></div>
  80. </body>
  81. </html>

P133. 定时器的应用(三)

上面已经基本完成了我们的需求,这节课我们将增加一些新的功能以及解决一些BUG。 BUG: 原来的代码,当我们想控制多个box时,由于定时器timer是唯一的,所以我们控制别的box会不小心关闭另一个box的进程。 新功能:

  • 我们可以不单单只能向左向右移动,可以向上向下,变宽变窄,使得box更多样化。
  • 增加一个回调函数,在动画执行完毕后调用,也可以不调用此参数。

解决BUG的方法:
我们不要再将timer设置为全局变量了,应该设置为box的一个方法,当我们点击按钮时,对应box对象的timer才开启定时器,关闭同理。
增加新功能的方法:

  • 增加一个attr参数,里面填入left、top、width等操作,然后函数也会执行对应的操作。
  • 增加回调函数可以使我们的程序更加灵活,如果我们想在动画执行完毕后,弹出一些提示框,可以利用回调函数,或者如果动画执行完毕后想再次执行动画,还可以使用回调函数。

最后,为了我们代码的可复制性,我们可以为我们的js和css代码封装到一个新的文件中,这样我们换一个文件还可以使用这些代码。
代码清单:

  1. //css部分
  2. *{
  3. padding: 0;
  4. margin: 0;
  5. }
  6. #box1{
  7. width: 100px;
  8. height: 100px;
  9. background-color: red;
  10. position: absolute;
  11. left:0;
  12. }
  13. #box3{
  14. width: 0px;
  15. border-right: 1px solid black;
  16. height: 1000px;
  17. background-color: black;
  18. position: absolute;
  19. top: 0px;
  20. left: 800px;
  21. }
  22. #box2{
  23. width: 100px;
  24. height: 100px;
  25. background-color:teal;
  26. position: absolute;
  27. top: 200px;
  28. left: 0;
  29. }
  1. //js部分
  2. function getStyle(obj,str){
  3. //利用或运算的优势,style等于网页中有的那个方法。
  4. style = obj.currentStyle || window.getComputedStyle(obj,null);
  5. return style[str];
  6. }
  7. //添加attr和回调函数
  8. function move(obj,attr,target,speed,callback){
  9. clearInterval(obj.timer);
  10. //获取元素当前的位置
  11. var current = parseInt(getStyle(obj,attr));
  12. //判断速度的正负值,如果0像800移动,speed为正,如果800向0移动,speed为负
  13. if (current > target){
  14. speed = -speed;
  15. }
  16. obj.timer = setInterval(function(){
  17. //只要获得回调函数中的值就好
  18. var oldLeft = parseInt(getStyle(obj,attr));
  19. var newLeft = oldLeft + speed;
  20. //利用speed正负判断方向
  21. //向右移动时,需要判断newLeft是否大于target
  22. //向左移动时,需要判断newLeft是否小于target
  23. if ((speed < 0 && newLeft < target) || (speed > 0 && newLeft > target)){
  24. newLeft = target;
  25. }
  26. //这里要改成[]而不能使用.操作
  27. obj.style[attr] = newLeft + "px";
  28. if (newLeft === target){
  29. //达到目标线,停止定时器
  30. clearInterval(obj.timer)
  31. //利用与操作符的作用,有传回调函数就调用
  32. callback && callback();
  33. }
  34. },20);
  35. }
  1. <!--html部分-->
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. <title>Document</title>
  9. <link href="./style.css" rel="stylesheet" type="text/css"/>
  10. <script type="text/javascript" src="./tools.js"></script>
  11. <script type="text/javascript">
  12. //本文件中的js代码只需要负责调用js文件中的函数就好。
  13. window.onload = function(){
  14. var btn1 = document.querySelector("#btn1");
  15. var btn2 = document.querySelector("#btn2");
  16. var btn3 = document.querySelector("#btn3");
  17. var btn4 = document.querySelector("#btn4");
  18. var box1 = document.querySelector("#box1");
  19. var box2 = document.querySelector("#box2");
  20. btn1.onclick = function(){
  21. move(box1,"left",800,30);
  22. };
  23. btn2.onclick = function(){
  24. move(box1,"left",0,10);
  25. };
  26. btn3.onclick = function(){
  27. move(box2,"width",800,10,function(){
  28. move(box2,"width",100,10);
  29. });
  30. }
  31. btn4.onclick = function(){
  32. move(box2,"width",100,10);
  33. }
  34. };
  35. </script>
  36. </head>
  37. <body>
  38. <button id="btn1" style="width: 100px;">box1向右移动</button>
  39. <button id="btn2" style="width: 100px;">box1向左移动</button>
  40. <button id="btn3" style="width: 100px;">box2向右移动</button>
  41. <button id="btn4" style="width: 100px;">box2向左移动</button>
  42. </br></br>
  43. <div id="box1"></div>
  44. <div id="box3"></div>
  45. <div id="box2"></div>
  46. </body>
  47. </html>

P134. 制作轮播图

P134—P137都是制作轮播图的课程,此处就不再过多的写笔记,仅展示代码部分,有需求请看原视频。

  1. //css部分
  2. *{
  3. margin: 0;
  4. padding: 0;
  5. }
  6. #outer{
  7. width: 620px;
  8. height: 400px;
  9. margin: 50px auto;
  10. background-color: rgb(122, 226, 240);
  11. padding: 10px 0;
  12. position: relative;
  13. overflow: hidden;
  14. }
  15. #imgList{
  16. list-style: none;
  17. position: absolute;
  18. left: 0px;
  19. }
  20. #imgList li{
  21. float: left;
  22. margin: 0 10px;
  23. }
  24. #navDiv{
  25. position: absolute;
  26. bottom: 20px;
  27. }
  28. #navDiv a{
  29. float: left;
  30. width: 15px;
  31. height: 15px;
  32. background-color: rgb(255, 99, 71);
  33. opacity: 0.7;
  34. transition: 50ms;
  35. /*透明度兼容IE8*/
  36. filter: alpha(opacity=50);
  37. margin: 0 5px;
  38. }
  39. #navDiv a:hover{
  40. background-color: rgb(112, 170, 218);
  41. }
  1. //js部分
  2. window.onload = function(){
  3. let imgList = document.querySelector("#imgList");
  4. let imgArr = document.querySelectorAll("img");
  5. imgList.style.width = 620*imgArr.length + "px";
  6. //设置导航按钮居中
  7. //获取navDIv
  8. let navDiv = document.querySelector("#navDiv");
  9. let outer = document.querySelector("#outer");
  10. navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth) / 2 + "px";
  11. //获取所有a标签
  12. let allA = document.querySelectorAll("a");
  13. //设置a标签索引
  14. index = 0;
  15. //设置默认选中的颜色
  16. allA[index].style.backgroundColor = "rgb(112, 170, 218)";
  17. for (let i = 0;i<allA.length;i++){
  18. //为每一个超链接都添加一个编号
  19. allA[i].num = i;
  20. allA[i].onclick = function(){
  21. //清空定时器
  22. clearInterval(timer);
  23. index = this.num;
  24. //设置标签变色
  25. setA();
  26. move(imgList,"left", -620*index ,70,function(){
  27. //由于前面关闭了定时器,这边要再开启
  28. autoChange();
  29. });
  30. }
  31. }
  32. //开启自动切换图片
  33. autoChange();
  34. //设置索引切换样式
  35. function setA(){
  36. /*我们采用一种偷梁换柱的方法,因为最后一张图片等于第一张图片,
  37. 所以将最后一张图片突然变成第一张图片,由于改变太快,肉眼是察觉不到的。
  38. */
  39. if (index >= imgArr.length - 1){
  40. index = 0;
  41. imgList.style.left = "0px";
  42. }
  43. //将所有a标签恢复默认颜色
  44. for (let i = 0;i<allA.length;i++){
  45. allA[i].style.backgroundColor = "";
  46. }
  47. allA[index].style.backgroundColor = "rgb(112, 170, 218)";
  48. }
  49. var timer;
  50. //自动切换图片函数
  51. function autoChange(){
  52. timer = setInterval(function(){
  53. //索引自增
  54. index++;
  55. index %= imgArr.length;
  56. move(imgList,"left", -620*index ,70,function(){
  57. //利用回调函数修改底部索引
  58. setA();
  59. });
  60. },3000);
  61. }
  62. };
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!--引用js文件和css文件-->
  9. <link type="text/css" rel="stylesheet" href="style.css"/>
  10. //tools文件就是上节课"定时器的应用(三)"中的js部分,script文件为上方js代码
  11. <script type="text/javascript" src="tools.js"></script>
  12. <script type="text/javascript" src="script.js"></script>
  13. </head>
  14. <body>
  15. <div id="outer">
  16. <ul id="imgList">
  17. <li><img src="./img/1.jpg" width="600px" height="400px"/></li>
  18. <li><img src="./img/2.jpg" width="600px" height="400px"/></li>
  19. <li><img src="./img/3.jpg" width="600px" height="400px"/></li>
  20. <li><img src="./img/4.jpg" width="600px" height="400px"/></li>
  21. <li><img src="./img/5.jpg" width="600px" height="400px"/></li>
  22. <li><img src="./img/1.jpg" width="600px" height="400px"/></li>
  23. </ul>
  24. <div id="navDiv">
  25. <a href="javascript:;"></a>
  26. <a href="javascript:;"></a>
  27. <a href="javascript:;"></a>
  28. <a href="javascript:;"></a>
  29. <a href="javascript:;"></a>
  30. </div>
  31. </div>
  32. </body>
  33. </html>

P137. 类的操作

我们假设有这么一段代码

  1. //css部分
  2. <style type="text/css">
  3. .b1{
  4. width: 100px;
  5. height: 100px;
  6. background-color: red;
  7. }
  8. </style>
  9. ...
  10. //html部分
  11. <body>
  12. <button id="btn1">点击按钮修改box样式</button>
  13. </br></br>
  14. <div id="box" class="b1"></div>
  15. </body>

我们现在想在js中设置点击按钮增加box的长和宽,那我们可以会这么做。

  1. <script type="text/javascript">
  2. window.onload = function(){
  3. //获取box
  4. var box = document.querySelector("#box");
  5. //获取btn1
  6. var btn1 = document.querySelector("#btn1");
  7. btn1.onclick = function(){
  8. box.style.width = "200px";
  9. box.style.height = "200px";
  10. }
  11. };
  12. </script>

这种方法是正确的,我们只需要调用对象的style属性即可,但是这种方法也有个不好的缺陷,那就是如果我们需求变化了,比如还要改变颜色,还要增加边框…这时,我们单纯的写一条条js代码就过于繁杂,并且不利于修改。
同时通过style属性来修改元素时,每修改一个样式,浏览器就需要重新渲染一次页面,这样执行的性能是比较差的。
我们希望,只需要一行代码,可以修改多个样式,我们可以通过修改类名的方式来实现这点。

  1. //css增加新的样式newb1
  2. .newb1{
  3. width: 200px;
  4. height: 200px;
  5. background-color: blue;
  6. }
  7. //js部分
  8. <script type="text/javascript">
  9. window.onload = function(){
  10. //获取box
  11. var box = document.querySelector("#box");
  12. //获取btn1
  13. var btn1 = document.querySelector("#btn1");
  14. btn1.onclick = function(){
  15. box.className = "newb1"; //这里只需要修改类名即可
  16. }
  17. };
  18. </script>
  19. //html部分不变

但是这里还有个问题,那就是如果我们只想修改高度,不想修改长度,然后我们把newb1样式中的宽度样式删了会发现,这时的宽度居然会继承父元素的宽度。这是因为我们是直接修改的类名,而替换的类中要是没有宽度这个样式,会自动继承父元素的宽度,那么我们应该怎么修改呢?

  1. //假设我们的替换的css不需要修改宽度
  2. .newb1{
  3. height: 200px;
  4. background-color: blue;
  5. }
  6. //单击响应函数修改为
  7. btn1.onclick = function(){
  8. box.className += " newb1"; //我们采用字符串拼串的方式,这里需要在前面加个空格
  9. }

上面这个写完了程序是可以正常运行了,表面看上去好像也没有问题,但是我们点击按钮后打开网页的审查元素一看,完了,随着我们点击按钮的次数增多,标签中的类名也会越变越多,这样虽然对我们的程序没什么影响,但是未免不太美观。
所以我们可以写一个函数,判断标签中是否已经有我们想要添加的类名,有我们就不添加了,还记得正则表达式吗?我们可以是有正则表达式来完成这个问题。

  1. <script type="text/javascript">
  2. window.onload = function(){
  3. //获取box
  4. var box = document.querySelector("#box");
  5. //获取btn1
  6. var btn1 = document.querySelector("#btn1");
  7. btn1.onclick = function(){
  8. //我们设置一个专门添加类名的函数,第一个参数为元素对象,第二个参数为类名
  9. addClass(box,"newb1");
  10. }
  11. };
  12. function addClass(obj,str){
  13. //进行判断,如果有那个类了,就不要再添加了
  14. if (!hasClass(obj,str)){
  15. obj.className += " " + str;
  16. }
  17. }
  18. function hasClass(obj,str){
  19. //需要检测单词边界
  20. var reg = new RegExp("\\b" + str + "\\b","g");
  21. //利用三目运算符简化代码,正则检测到了就返回true,没检测到返回false
  22. return reg.test(obj.className) ? true : false;
  23. }
  24. </script>

运用上面的知识,我们可以再为我们的网页添加一个删除类的函数。

  1. function removeClass(obj,str){
  2. var reg = new RegExp(" \\b" + str + "\\b","g");
  3. obj.className = obj.className.replace(reg,"");
  4. }

最后,我们把前面的函数整合一下,创建一个toggleClass函数,这个函数可以切换我们的类,如果元素中具有该类,则删除,反之,则添加。

  1. function toggleClass(obj,str){
  2. //利用hasClass函数判断
  3. if (hasClass(obj,str)){
  4. removeClass(obj,str);
  5. }
  6. else{
  7. addClass(obj,str);
  8. }
  9. }

如果我们把这个函数添加到我们按钮的单击响应函数当中,我们就可以实现有类的时候删除类,无类的时候添加类。
最终代码:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style type="text/css">
  9. .b1{
  10. width: 100px;
  11. height: 100px;
  12. background-color: red;
  13. }
  14. .newb1{
  15. height: 200px;
  16. background-color: blue;
  17. }
  18. .newb2{
  19. width: 400px;
  20. height: 200px;
  21. background-color: blue;
  22. }
  23. </style>
  24. <script type="text/javascript">
  25. window.onload = function(){
  26. //获取box
  27. var box = document.querySelector("#box");
  28. //获取btn1
  29. var btn1 = document.querySelector("#btn1");
  30. btn1.onclick = function(){
  31. //调用函数
  32. toggleClass(box,"newb2")
  33. }
  34. };
  35. //添加类
  36. function addClass(obj,str){
  37. if (!hasClass(obj,str)){
  38. obj.className += " " + str;
  39. }
  40. }
  41. //判断类是否存在
  42. function hasClass(obj,str){
  43. //需要检测单词边界
  44. var reg = new RegExp("\\b" + str + "\\b","g");
  45. //利用三目运算符简化代码,正则检测到了就返回true,没检测到返回false
  46. return reg.test(obj.className) ? true : false;
  47. }
  48. //删除类
  49. function removeClass(obj,str){
  50. var reg = new RegExp(" \\b" + str + "\\b","g");
  51. obj.className = obj.className.replace(reg,"");
  52. }
  53. //切换类
  54. function toggleClass(obj,str){
  55. if (hasClass(obj,str)){
  56. removeClass(obj,str);
  57. }
  58. else{
  59. addClass(obj,str);
  60. }
  61. }
  62. </script>
  63. </head>
  64. <body>
  65. <button id="btn1">点击按钮修改box样式</button>
  66. </br></br>
  67. <div id="box" class="b1 newb2 newb1"></div>
  68. </body>
  69. </html>

P138. 二级菜单

P138-P139来尝试实现一个二级菜单的网页,由于我这没有老师css和HTMl的源码,这两部分由我依据模样大概制作完毕,仅作为参考。

  1. //CSS部分
  2. *{
  3. padding: 0;
  4. margin: 0;
  5. list-style-type: none;
  6. }
  7. a,img{
  8. border: 0;
  9. text-decoration: none;
  10. }
  11. body{
  12. font: 12px/180% Arial, Helvetica,sans-serif,"新宋体";
  13. }
  14. #my_menu{
  15. width: 200px;
  16. text-align: center;
  17. background-color: blanchedalmond;
  18. margin: 50px auto;
  19. cursor: pointer;
  20. user-select: none;
  21. border-radius: 10px;
  22. padding-bottom: 10px;
  23. overflow: hidden;
  24. }
  25. .collapsed{
  26. width: 100%;
  27. height: 25px;
  28. }
  29. .menuSpan{
  30. display: block;
  31. line-height: 25px;
  32. background-color: rgb(95, 216, 166);
  33. }
  34. a{
  35. display: block;
  36. color: rgb(16, 39, 16);
  37. height: 30px;
  38. line-height: 30px;
  39. transition: 70ms all;
  40. }
  41. a:hover{
  42. background-color: brown;
  43. color: white;
  44. }
  1. //tools工具包
  2. function getStyle(obj,str){
  3. //利用或运算的优势,style等于网页中有的那个方法。
  4. style = obj.currentStyle || window.getComputedStyle(obj,null);
  5. return style[str];
  6. }
  7. //imgList,"left", -620*index ,70
  8. function move(obj,attr,target,speed,callback){
  9. clearInterval(obj.timer);
  10. //获取元素当前的位置
  11. var current = parseInt(getStyle(obj,attr));
  12. //如果你当前位置大于你目标位置,speed为负,如果你当前位置小于目标位置,speed为正
  13. if (current > target){
  14. speed = -speed;
  15. }
  16. //开启定时器
  17. obj.timer = setInterval(function(){
  18. var oldLeft = parseInt(getStyle(obj,attr));
  19. var newLeft = oldLeft + speed;
  20. //利用speed正负判断方向
  21. //向右移动时,需要判断newLeft是否大于target
  22. //向左移动时,需要判断newLeft是否小于target
  23. if ((speed < 0 && newLeft < target) || (speed > 0 && newLeft > target)){
  24. newLeft = target;
  25. }
  26. obj.style[attr] = newLeft + "px";
  27. if (newLeft === target){
  28. //达到目标线,停止定时器
  29. clearInterval(obj.timer)
  30. //调用回调函数
  31. callback && callback();
  32. }
  33. },20);
  34. }
  35. function addClass(obj,str){
  36. if (!hasClass(obj,str)){
  37. obj.className += " " + str;
  38. }
  39. }
  40. function hasClass(obj,str){
  41. //需要检测单词边界
  42. var reg = new RegExp("\\b" + str + "\\b","g");
  43. //利用三目运算符简化代码,正则检测到了就返回true,没检测到返回false
  44. return reg.test(obj.className) ? true : false;
  45. }
  46. function removeClass(obj,str){
  47. if (obj.className = ""){
  48. var reg = new RegExp("\\b" + str + "\\b","g");
  49. }else{
  50. var reg = new RegExp(" \\b" + str + "\\b","g");
  51. }
  52. obj.className = obj.className.replace(reg,"");
  53. }
  54. function toggleClass(obj,str){
  55. if (hasClass(obj,str)){
  56. removeClass(obj,str);
  57. }
  58. else{
  59. addClass(obj,str);
  60. }
  61. }
  1. <!--html部分-->
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. <title>Document</title>
  9. <!--引入外部的css和js文件,tools文件为上方代码-->
  10. <link type="text/css" rel="stylesheet" href="./css/style.css"/>
  11. <script type="text/javascript" src="./js/tools.js"></script>
  12. <script type="text/javascript">
  13. window.onload = function(){
  14. /*每一个菜单都是一个div
  15. * 当div具有collapsed这个类时,div就是折叠状态
  16. * 反之就是展开状态
  17. */
  18. //获取所有类名为menuSpan的标签
  19. var menuSpan = document.querySelectorAll(".menuSpan");
  20. //定义一个变量,保存当前以打开的菜单
  21. var openDiv = menuSpan[0].parentNode;
  22. for (var i = 0;i<menuSpan.length;i++){
  23. menuSpan[i].onclick = function(){
  24. /* alert("hh"); */
  25. var parentDiv = this.parentNode;
  26. toggleMenu(parentDiv);
  27. //判断parentDiv和openDiv是否相等
  28. if (parentDiv != openDiv && !hasClass(openDiv,"collapsed")){
  29. //关闭当前打开的菜单
  30. toggleMenu(openDiv);
  31. }
  32. openDiv = parentDiv;
  33. }
  34. }
  35. function toggleMenu(obj){
  36. var begin = obj.offsetHeight;
  37. //切换菜单的展开与折叠
  38. toggleClass(obj,"collapsed");
  39. var end = obj.offsetHeight;
  40. //执行动画,从begin向end过渡
  41. obj.style.height = begin + "px";
  42. move(obj,"height",end,10,function(){
  43. obj.style.height = ""
  44. });
  45. }
  46. };
  47. </script>
  48. </head>
  49. <body>
  50. <div id="my_menu" class="sdmenu">
  51. <div style="overflow: hidden;margin: 3px 0;">
  52. <span class="menuSpan">在线工具</span>
  53. <a href="#">图像优化</a>
  54. <a href="#">图标生成器</a>
  55. <a href="#">邮件</a>
  56. <a href="#">password密码</a>
  57. <a href="#">地图图像</a>
  58. <a href="#">按钮生成器</a>
  59. </div>
  60. <!--collapsed意为折叠-->
  61. <div class="collapsed" style="overflow: hidden;margin: 3px 0;">
  62. <span class="menuSpan">支持我们</span>
  63. <a href="#">推荐我们</a>
  64. <a href="#">关心我们</a>
  65. <a href="#">了解我们</a>
  66. </div>
  67. <div class="collapsed" style="overflow: hidden;margin: 3px 0;">
  68. <span class="menuSpan">合作伙伴</span>
  69. <a href="#">腾讯视频</a>
  70. <a href="#">阿里巴巴集团</a>
  71. <a href="#">网易邮箱</a>
  72. </div>
  73. <div class="collapsed" style="overflow: hidden;margin: 3px 0;">
  74. <span class="menuSpan">测试电流</span>
  75. <a href="#">what you name?</a>
  76. <a href="#">what you name?</a>
  77. <a href="#">what you name?</a>
  78. <a href="#">what you name?</a>
  79. <a href="#">what you name?</a>
  80. </div>
  81. </div>
  82. </body>
  83. </html>

P140. JSON

我们了来创建一个对象

  1. var obj = {name:"张三",age:15,gender:"男"};
  2. console.log(obj.name);

我们输出这个对象,可以发现是没有任何问题的,但是未来我们如果去做项目,很有可能会有一个需求,就是需要和后台服务器去做交互,毕竟一个网站是由前端,还需要后台服务器对我们的网页提供支持。
可是我们要和服务器做交互,但是服务器用的语言可以JAVA,C++…并不是使用JavaScript写的,可是我们现在有个对象,我们需要传给服务器,可是JS中的对象,只有JS认识,服务器传过来的对象只有服务器认识。
那我们想想,有什么是JS和其他任何语言都认识的东西呢,比如整数、布尔值、字符串…这些类型是任何语言都有的东西,那我们转换成什么好呢,整数?太麻烦了;布尔值?true和false无法表达我们需要传达的那么多信息;字符串呢?字符串就刚刚好,字符串任何语言都认识,甚至是我们自己看,都能看出表达的意思。

  1. var obj = '{"name":"张三","age":15,"gender":"男"}';
  2. //将对象转换成一个字符串
  3. console.log(typeof(obj));

概念

JSON -> JavaScript Object Notation (JS对象表示法)
JSON就是一个特殊格式的字符串,这个字符串可以被任意语言所识别,并且可以转换成任意语言中的对象,JSON在开发中主要用于数据的交互

JSON规则

  • JSON和JS对象格式一样,只不过JSON字符串中的属性名必须加双引号!!其他和JS语法一致。
  • JS分类
      1. 对象{}
      1. 数组[]
  • JSON中允许的值
    • 1.字符串
    • 2.数值
    • 3.布尔值
    • 4.null
    • 5.对象(不包括函数对象)
    • 6.数组

如上方所示,修改为字符串之后,我们会发现我们也无法调用JSON字符串中的对象了,所以在JS中,为我们提供了一个工具类,就叫JSON,这个对象可以帮我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON。

JSON -> JS对象

  • JSON.parse()方法

    • 可以将一个json字符串转换为js对象
    • 它需要一个JSON字符串作为参数
      1. var json_str = '{"content":[1,2,3,4],"lens":2}'
      2. var obj = JSON.parse(json_str);
      3. console.log(obj.content[2]);
      4. //控制台会输出content中的数组中的3

      JS对象 -> JSON

  • JSON.stringify()方法

    • 可以将一个JS对象转换成JSON字符串
    • 需要一个JS对象作为参数
      1. //虽然可以使用手工加引号,但是在程序中不建议这么做
      2. var obj = {name:"吕布",age:18};
      3. var json_str = JSON.stringify(obj);
      4. console.log(json_str);
      可是如果我们去IE7的环境下运行代码,我们会发现JSON这个工具这个工具不支持IE7,为了兼容IE7,我们可以使用eval()函数

      eval()函数

  • 这个函数可以用来执行一段字符串形式的代码,并将执行结果返回。

  • 如果使用eval()执行的字符串中含有{},它会将{}当成一个代码块,如果不希望被当成代码块来解析,需要在字符串前后加上()

    1. var test = '{"name":"刘备","age":18}';
    2. var obj = eval("(" + test + ")");
    3. console.log(obj.name);
  • eval()这个函数的功能很强大,可以直接执行一串字符串中的JS代码,但是在开发中不建议使用,首先它的执行性能较差,其次它还具有安全隐患。

实际中兼容IE7的情况已经很少了,所以我们不推荐用这个方法。