昨日作业讲解:

京东购物车

京东购物车效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图1

实现原理:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图2

用 2 个盒子,就可以完整效果。

先让上面的小盒子向下移动 1px,此时就出现了压盖效果。小盒子设置 z-index 压盖大盒子,将小盒子的下边框去掉,就可以实现效果。

代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style type="text/css">
  7. *{
  8. padding: 0;
  9. margin: 0;
  10. }
  11. /*背景盒子*/
  12. .box{
  13. width: 500px;
  14. height: 110px;
  15. margin: 100px auto;
  16. background-color: rgba(0,0,0,0.2);
  17. /*相对定位*/
  18. position: relative;
  19. }
  20. /*购物车*/
  21. .car{
  22. width: 150px;
  23. height: 30px;
  24. background-color: #fff;
  25. /*设置绝对定位,参考对象为box*/
  26. position: absolute;
  27. left: 200px;
  28. /*这里必须是3.1,如果是3,放大时,会看到细线*/
  29. top: 3.1px;
  30. /*设置元素的堆叠顺序*/
  31. z-index: 9;
  32. border: 1px solid green;
  33. }
  34. .shop{
  35. width: 310px;
  36. height: 70px;
  37. background-color: #fff;
  38. position: absolute;
  39. top:33px;
  40. left: 40px;
  41. border: 1px solid green;
  42. /*隐藏不显示*/
  43. display: none;
  44. }
  45. /*去掉底部的边框*/
  46. div.c{
  47. border-bottom-width: 0;
  48. }
  49. /*设置盒子边框*/
  50. div.t{
  51. border: 1px solid green;
  52. }
  53. </style>
  54. </head>
  55. <body>
  56. <div class="box">
  57. <div class="car" id="myCar">我的购物车</div>
  58. <div class="shop t" id="shop"></div>
  59. </div>
  60. <script type="text/javascript">
  61. var myCar = document.getElementById('myCar'); //小盒子
  62. var shop = document.getElementById('shop'); //大盒子
  63. //onmouseenter 事件在鼠标指针移动到元素上时触发
  64. myCar.onmouseenter = function(){
  65. shop.style.display = 'block'; //此元素将显示为块级元素
  66. myCar.className += ' c'; //去掉底部的边框
  67. }
  68. // onmouseleave 事件在鼠标移除元素时触发
  69. myCar.onmouseleave = function(){
  70. //大盒子隐藏
  71. shop.style.display = 'none'; //此元素不会被显示
  72. myCar.removeAttribute('class'); //删除class属性,此时有2个class,分别是car和c。都会被删除
  73. myCar.className = 'car'; //重新设置class为car,让它显示默认样式。
  74. }
  75. </script>
  76. </body>
  77. </html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图3

一、关于 DOM 操作的相关案例

1.模态框案例

需求:

打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击 X 的时候会关闭当前的模态框

第一种方法,先创建一个 div,默认隐藏

第二种方法,使用 dom,来创建 div。

下面主要采用第二种方法,能把昨天学习的内容应用的到

代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style type="text/css">
  7. *{
  8. padding: 0;
  9. margin: 0;
  10. }
  11. html,body{
  12. height: 100%;
  13. }
  14. #box{
  15. width: 100%;
  16. height: 100%;
  17. background: rgba(0,0,0,.3);
  18. }
  19. #content{
  20. position: relative;
  21. top: 150px;
  22. width: 400px;
  23. height: 200px;
  24. line-height: 200px;
  25. text-align: center;
  26. color: red;
  27. background-color: #fff;
  28. margin: auto;
  29. }
  30. #span1{
  31. position: absolute;
  32. background-color: red;
  33. top: 0;
  34. right: 0;
  35. width: 30px;
  36. height: 30px;
  37. line-height: 30px;
  38. text-align: center;
  39. color: #fff;
  40. }
  41. </style>
  42. </head>
  43. <body>
  44. <button id="btn" style="margin-left: 50%">弹出</button>
  45. </body>
  46. <script type="text/javascript">
  47. //获取dom元素 1.获取事件源
  48. var oBtn = document.getElementById('btn');
  49. //创建弹出模态框的相关DOM对象
  50. var oDiv = document.createElement('div');
  51. var oP = document.createElement('p');
  52. var oSpan = document.createElement('span');
  53. // 设置属性
  54. oDiv.id = 'box';
  55. oP.id = 'content'
  56. oP.innerHTML = '模态框成功弹出'
  57. oSpan.innerHTML = 'X';
  58. oSpan.id = 'span1'
  59. // 追加元素
  60. oDiv.appendChild(oP);
  61. oP.appendChild(oSpan);
  62. // 点击弹出按钮 弹出模态框
  63. oBtn.onclick = function(){
  64. //动态的添加到body中一个div
  65. // insertBefore(插入的元素,参考节点)
  66. this.parentNode.insertBefore(oDiv,btn)
  67. }
  68. // 点击X 关闭模态框
  69. oSpan.onclick = function(){
  70. // 移除oDiv元素
  71. oDiv.parentNode.removeChild(oDiv) //由于div有多个元素,直接移除整个div即可
  72. }
  73. </script>
  74. </html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图4

2.简易留言板

需求:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图5

当在 textarea 中输入内容,点击留言按钮,会添加到浏览器中

图如下:

图如下:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图6

代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>留言板</title>
  6. <style type="text/css">
  7. *{
  8. padding: 0;
  9. margin: 0;
  10. }
  11. /*去掉默认的ul样式*/
  12. ul {
  13. list-style: none;
  14. }
  15. .close{
  16. /*inline-block 通俗来讲,不独占一行的块级元素*/
  17. display: inline-block;
  18. width: 20px;
  19. height: 20px;
  20. line-height: 20px;
  21. text-align: center;
  22. /*cursor显示的指针(光标)的类型
  23. pointer 光标呈现为指示链接的指针(一只手)
  24. */
  25. cursor: pointer;
  26. background-color: rgba(0,0,0,.1);
  27. margin-left: 20px;
  28. }
  29. </style>
  30. </head>
  31. <body>
  32. <div style="margin-left: 20px">
  33. <h1>简易留言板</h1>
  34. <div id="box">
  35. <!--<ul></ul>-->
  36. </div>
  37. <textarea id="msg"></textarea>
  38. <input type="button" id="btn" value="留言"/>
  39. <button onclick="sum()">统计</button>
  40. </div>
  41. </body>
  42. <script type="text/javascript">
  43. // 0 将ul标签添加到div#box标签中
  44. var oUl = document.createElement('ul'); //创建ul标签
  45. var oBox = document.getElementById('box'); //获取box对象
  46. oBox.appendChild(oUl); //添加到box中
  47. var oBtn = document.getElementById('btn'); //获取btn对象
  48. var oMsg = document.getElementById('msg')
  49. // 控制留言的总数量
  50. var count = 0; //默认为0
  51. oBtn.onclick = function(){
  52. // 点击留言按钮事件操作
  53. // 1.创建li标签
  54. var oLi = document.createElement('li');
  55. //2.设置内容
  56. oLi.innerHTML = oMsg.value + "<span class='close'>X</span>" //输入框内容+X图标
  57. // 3.如果想在插入的第一个li获取的前面继续添加li标签
  58. //3.1 获取li标签
  59. var olis = document.getElementsByTagName('li');
  60. //3.2 如果是第一次添加的li标签,则直接添加到ul的后面
  61. if(olis.length == 0){ //默认长度为0
  62. oUl.appendChild(oLi);
  63. count++; //统计留言个数
  64. }else{
  65. // 3.3 如果不是第一次添加的li标签,则插入到第一个li标签的前面
  66. oUl.insertBefore(oLi,olis[0]);
  67. count++;
  68. }
  69. // 4.添加完成之后 清空textarea的值
  70. oMsg.value = '';
  71. // 5.点击X的时候删除当前的一条数据
  72. //5.1 先获取所有的X
  73. var oSpans = document.getElementsByTagName('span');
  74. // 5.2 for循环 对所有的X添加点击事件
  75. for(var i = 0; i< oSpans.length; i++){
  76. oSpans[i].onclick = function(){
  77. // 5.3 移除当前的li标签
  78. oUl.removeChild(this.parentNode)
  79. count--; //统计结果减1
  80. }
  81. }
  82. }
  83. //显示统计结果
  84. function sum(){
  85. alert('一共发布了'+count+'条留言');
  86. }
  87. </script>
  88. </html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图7

3.使用 js 模拟选择器中 hover

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. button {
  8. margin: 10px;
  9. width: 100px;
  10. height: 40px;
  11. /*设置光标为一只手*/
  12. cursor: pointer;
  13. }
  14. /*背景颜色*/
  15. .current {
  16. background-color: red;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <button>按钮1</button>
  22. <button>按钮2</button>
  23. <button>按钮3</button>
  24. <button>按钮4</button>
  25. <button>按钮5</button>
  26. <script>
  27. //需求:鼠标放到哪个button上,改button变成黄色背景(添加类)
  28. //获取button按钮
  29. var btnArr = document.getElementsByTagName("button");
  30. //绑定事件
  31. for(var i=0;i<btnArr.length;i++){ //要为每一个按钮绑定事件,所以用到了for循环
  32. btnArr[i].onmouseover = function () {
  33. //【重要】排他思想:先把所有按钮的className设置为空,然后把我(this)这个按钮的className设置为current
  34. //排他思想和for循环连用
  35. for(var j=0;j<btnArr.length;j++){
  36. btnArr[j].className = ""; //清空class
  37. }
  38. this.className = "current"; //【重要】核心代码
  39. }
  40. }
  41. //鼠标离开current时,还原背景色
  42. for(var i=0;i<btnArr.length;i++){ //要为每一个按钮绑定事件,所以用到了for循环
  43. btnArr[i].onmouseout = function () { //鼠标离开任何一个按钮时,就把按钮的背景色还原
  44. this.className = ""; //清空class
  45. }
  46. }
  47. </script>
  48. </body>
  49. </html>

代码解释:

鼠标悬停时,current 栏变色,这里用到了排他思想:先把所有按钮的 className 设置为空,然后把我(this)这个按钮的 className 设置为 current,就可以达到变色的效果。核心代码是:

//排他思想:先把所有按钮的className设置为空,然后把我(this)这个按钮的className设置为current

  1. //排他思想和for循环连用
  2. for(var j=0;j<btnArr.length;j++){
  3. btnArr[j].className = "";
  4. }
  5. this.className = "current";

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图8

4.tab 栏选项卡

代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style type="text/css">
  7. *{
  8. padding: 0;
  9. margin: 0;
  10. }
  11. /*去除ul默认样式*/
  12. ul{
  13. list-style: none;
  14. }
  15. #tab{
  16. width: 480px;
  17. margin: 20px auto;
  18. border: 1px solid red;
  19. }
  20. ul{
  21. width: 100%;
  22. /*清除浮动*/
  23. overflow: hidden;
  24. }
  25. ul li{
  26. float: left;
  27. width: 160px;
  28. height: 60px;
  29. line-height: 60px;
  30. text-align: center;
  31. background-color: #cccccc;
  32. }
  33. ul li a{
  34. /*去除a标签下划线*/
  35. text-decoration: none;
  36. /*颜色为黑色*/
  37. color:black;
  38. }
  39. li.active{
  40. background-color: red;
  41. }
  42. /*隐藏P标签*/
  43. p{
  44. display: none;
  45. height: 200px;
  46. text-align: center;
  47. line-height: 200px;
  48. background-color: red;
  49. }
  50. /*显示P标签*/
  51. p.active{
  52. display: block;
  53. }
  54. </style>
  55. </head>
  56. <body>
  57. <div id="tab">
  58. <ul>
  59. <li class="active">
  60. <a href="#">首页</a>
  61. </li>
  62. <li>
  63. <a href="#">新闻</a>
  64. </li>
  65. <li>
  66. <a href="#">图片</a>
  67. </li>
  68. </ul>
  69. <p class="active">首页内容</p>
  70. <p>新闻内容</p>
  71. <p>图片内容</p>
  72. </div>
  73. </body>
  74. <script type="text/javascript">
  75. window.onload = function(){
  76. // //需求:鼠标放到上面的li上,li本身变色(添加类),对应的p也显示出来(添加类);
  77. //思路:1.点亮上面的盒子。 2.利用索引值显示下面的盒子。
  78. var tabli = document.getElementsByTagName('li'); //获取li标签
  79. var tabContent = document.getElementsByTagName('p') //获取p标签
  80. for(var i = 0; i < tabli.length; i++){
  81. // 绑定索引值(新增一个自定义属性:index属性)
  82. //下面的绑定事件无法直接获取i,所以这里定义了一个属性i,让它成为全局变量
  83. tabli[i].index = i;
  84. // 绑定点击事件
  85. tabli[i].onclick = function(){
  86. // 1.点亮上面的盒子。 2.利用索引值显示下面的盒子。(排他思想)
  87. for(var j = 0; j < tabli.length; j++){
  88. tabli[j].className = ''; //清空li标签的class
  89. tabContent[j].className = ''; //清空p标签的class,那么p标签会隐藏
  90. }
  91. this.className = 'active' //li标签显示背景颜色
  92. //p标签设置class为active,表示显示p标签
  93. tabContent[this.index].className = 'active';//【重要代码】
  94. }
  95. }
  96. }
  97. </script>
  98. </html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图9

一个{}表示一个作用域,多个作用域之间的变量是不能直接引用的。怎么办呢?

将变量设置为全局变量,就可以调用了。

虽然事件的作用域在 for 循环的下面,但是它们是 2 个不同的作用域,不能调用 i

所以上面的代码中,加了一行,就是为了解决这个问题的。

  1. tabli[i].index = i;

5、购物车案例

请参考上面的作业讲解

二、JS 中的面向对象

js 中没有 class 的概念,它是一个伪面向对象。因为它没有多态!

创建对象的几种常用方式

1.使用 Object 或对象字面量创建对象

2.工厂模式创建对象

3.构造函数模式创建对象

4.原型模式创建对象

1.使用 Object 或对象字面量创建对象

JS 中最基本创建对象的方式:

  1. var student = new Object();
  2. student.name = "easy";
  3. student.age = "20";
  4. console.log(student);

查看结果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图10

这样,一个 student 对象就创建完毕,拥有 2 个属性 name 以及 age,分别赋值为”easy”和 20。

如果你嫌这种方法有一种封装性不良的感觉。来一个对象字面量方式创建对象。

  1. var student = {
  2. name : "easy",
  3. age : 20
  4. };
  5. console.log(student);

查看结果,效果同上!

这样看起来似乎就完美了。但是马上我们就会发现一个十分尖锐的问题:当我们要创建同类的 student1,student2,…,studentn时,我们不得不将以上的代码重复n次….

  1. var sutdent1 = {
  2. name : "easy1",
  3. age : 20
  4. };
  5. var sutdent2 = {
  6. name : "easy2",
  7. age : 20
  8. };
  9. ...
  10. var sutdentn = {
  11. name : "easyn",
  12. age : 20
  13. };

有个提问?能不能像工厂车间那样,有一个车床就不断生产出对象呢?我们看”工厂模式”。

2.工厂模式创建对象

JS 中没有类的概念,那么我们不妨就使用一种函数将以上对象创建过程封装起来以便于重复调用,同时可以给出特定接口来初始化对象

  1. function createStudent(name, age) {
  2. var obj = new Object();
  3. obj.name = name;
  4. obj.age = age;
  5. return obj;
  6. }
  7. var student1 = createStudent("easy1", 20);
  8. var student2 = createStudent("easy2", 20);
  9. ...
  10. var studentn = createStudent("easyn", 20);

这样一来我们就可以通过 createStudent 函数源源不断地”生产”对象了。看起来已经高枕无忧了,但贪婪的人类总有不满足于现状的天性:我们不仅希望”产品”的生产可以像工厂车间一般源源不断,我们还想知道生产的产品究竟是哪一种类型的。

比如说,我们同时又定义了”生产”水果对象的 createFruit()函数:

  1. function createFruit(name, color) {
  2. var obj = new Object();
  3. obj.name = name;
  4. obj.color = color;
  5. return obj;
  6. }
  7. var v1 = createStudent("easy1", 20);
  8. var v2 = createFruit("apple", "green");

对于以上代码创建的对象 v1、v2,我们用 instanceof 操作符去检测,他们统统都是 Object 类型。我们的当然不满足于此,我们希望 v1 是 Student 类型的,而 v2 是 Fruit 类型的。为了实现这个目标,我们可以用自定义构造函数的方法来创建对象

3.构造函数模式创建对象

在上面创建 Object 这样的原生对象的时候,我们就使用过其构造函数:

  1. var obj = new Object();

在创建原生数组 Array 类型对象时也使用过其构造函数:

  1. var arr = new Array(10); //构造一个初始长度为10的数组对象

在进行自定义构造函数创建对象之前,我们首先了解一下构造函数和普通函数有什么区别。

1、实际上并不存在创建构造函数的特殊语法,其与普通函数唯一的区别在于调用方法。对于任意函数,使用 new 操作符调用,那么它就是构造函数;不使用 new 操作符调用,那么它就是普通函数。

2、按照惯例,我们约定构造函数名以大写字母开头,普通函数以小写字母开头,这样有利于显性区分二者。例如上面的 new Array(),new Object()。

3、使用 new 操作符调用构造函数时,会经历(1)创建一个新对象;(2)将构造函数作用域赋给新对象(使 this 指向该新对象);(3)执行构造函数代码;(4)返回新对象;4 个阶段。

ok,了解了构造函数和普通函数的区别之后,我们使用构造函数将工厂模式的函数重写,并添加一个方法属性:

  1. function Student(name, age) {
  2. this.name = name;
  3. this.age = age;
  4. this.alertName = function(){
  5. alert(this.name)
  6. };
  7. }
  8. function Fruit(name, color) {
  9. this.name = name;
  10. this.color = color;
  11. this.alertName = function(){
  12. alert(this.name)
  13. };
  14. }

这样我们再分别创建 Student 和 Fruit 的对象:

  1. var v1 = new Student("easy", 20);
  2. var v2 = new Fruit("apple", "green");

这时我们再来用 instanceof 操作符来检测以上对象类型就可以区分出 Student 以及 Fruit 了:

  1. alert(v1 instanceof Student); //true
  2. alert(v2 instanceof Student); //false
  3. alert(v1 instanceof Fruit); //false
  4. alert(v2 instanceof Fruit); //true
  5. alert(v1 instanceof Object); //true 任何对象均继承自Object
  6. alert(v2 instanceof Object); //true 任何对象均继承自Object

这样我们就解决了工厂模式无法区分对象类型的尴尬。那么使用构造方法来创建对象是否已经完美了呢?使用构造器函数通常在 js 中我们来创建对象。

我们会发现 Student 和 Fruit 对象中共有同样的方法,当我们进行调用的时候这无疑是内存的消耗。

我们完全可以在执行该函数的时候再这样做,办法是将对象方法移到构造函数外部:

  1. function Student(name, age) {
  2. this.name = name;
  3. this.age = age;
  4. this.alertName = alertName;
  5. }
  6. function alertName() {
  7. alert(this.name);
  8. }
  9. var stu1 = new Student("easy1", 20);
  10. var stu2 = new Student("easy2", 20);

在调用 stu1.alertName()时,this 对象才被绑定到 stu1 上。

我们通过将 alertName()函数定义为全局函数,这样对象中的 alertName 属性则被设置为指向该全局函数的指针。由此 stu1 和 stu2 共享了该全局函数,解决了内存浪费的问题

但是,通过全局函数的方式解决对象内部共享的问题,终究不像一个好的解决方法。如果这样定义的全局函数多了,我们想要将自定义对象封装的初衷便几乎无法实现了。更好的方案是通过原型对象模式来解决。

4.原型的模式创建对象

原型链甚至原型继承,是整个 JS 中最难的一部分也是最不好理解的一部分,在这里由于我们课程定位的原因,如果对 js 有兴趣的同学,可以去查阅一下相关 JS 原型的一些知识点。更加有助于你以后前端 JS 的面试。

  1. //var arry = new Array()
  2. function Student() {
  3. // Student this指的就是当前对象 设置对象的属性
  4. this.name = 'easy';
  5. this.age = 20;
  6. }
  7. // 伪面向对象 多态
  8. Student.prototype.alertName = function(){
  9. console.log(this.name);
  10. };
  11. Student.prototype.showAge = function(){
  12. console.log(this.age);
  13. }
  14. var stu1 = new Student();
  15. var stu2 = new Student();
  16. console.log(stu1);
  17. stu1.alertName(); //easy
  18. stu2.alertName(); //easy
  19. stu1.showAge(); //20
  20. console.log(stu1.alertName == stu2.alertName); //true 二者共享同一函数

查看结果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图11

第 4 种方式和第 1 种方式中的红色部分,都要熟练掌握。其他方式,仅做了解。

三、定时器

在 js 中的定时器分两种:1、setTimeout() 2、setInterval()

这 2 种方式,都很常用的。setTimeout 只能执行一次,它是异步的。

事件操作,是属于异步的。

举例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div id="app" style="width: 100px;height: 100px;border: 1px solid red;"></div>
    <script type="text/javascript">
        console.log(111);
        document.getElementById('app').onclick = function () {
            console.log(222);
        }
        console.log(333);
    </script>
</body>
</html>

查看 console,当点击红框的时候,才输出 222,说明事件是异步执行的。触发时,才执行。

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图12

1.setTimeOut()

只在指定时间后执行一次

//定时器 异步运行 
function hello(){ 
alert("hello"); 
} 
//使用方法名字执行方法 
var t1 = window.setTimeout(hello,1000); 
var t2 = window.setTimeout("hello()",3000);//使用字符串执行方法 
window.clearTimeout(t1);//去掉定时器

访问网页,等待 1 秒后,弹框

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图13

举例:

console.log(111);
//一般是这种写法,funciton就是回调函数
setTimeout(function () {
    console.log(222);
},1000);
console.log(333);

查看 console,等待 1 秒后输出 222

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图14

2.setInterval()

在指定时间为周期循环执行

/实时刷新  时间单位为毫秒 
setInterval('refreshQuery()',8000);  
/* 刷新查询 */ 
function refreshQuery(){ 
  console.log('每8秒调一次')
}

两种方法根据不同的场景和业务需求择而取之,

对于这两个方法,需要注意的是如果要求在每隔一个固定的时间间隔后就精确地执行某动作,那么最好使用 setInterval,而如果不想由于连续调用产生互相干扰的问题,尤其是每次函数的调用需要繁重的计算以及很长的处理时间,那么最好使用 setTimeout

让一个 div 匀速运动

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app" style="width: 100px;height: 100px;border: 1px solid red;"></div>


<button id="move">移动</button>
<script type="text/javascript">
    var oApp = document.getElementById('app');  //获取div对象
    var moveBtn = document.getElementById('move');  //获取button


    var count = 0;  //初始步数
    var timer = null;  //定义一个空对象
    moveBtn.onclick = function(){
        timer = setInterval(function(){
            //控制步距
            count+=3;
            //当移动到500px时,停止运动
            if (count>=500) {
                clearInterval(timer);  //去掉定时器
            }
            console.log(count);  //打印步数
            oApp.style.marginLeft = count + 'px';
        },30);  //30表示30微秒
    }
</script>


</body>
</html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图15

定时器有一个弊端,它会消耗内存

在某个时机,要清理定时器!

尽量少用定时器,常用的还是 setTimeout

思考题,移动到某个位置,比如 500,再弹回来

四、BOM

bom 用的很少,仅做了解

BOM 的介绍

JavaScript 基础分为三个部分:

  • ECMAScript:JavaScript 的语法标准。包括变量、表达式、运算符、函数、if 语句、for 语句等。
  • DOM:文档对象模型,操作网页上的元素的 API。比如让盒子移动、变色、轮播图等。
  • BOM:浏览器对象模型,操作浏览器部分功能的 API。比如让浏览器自动滚动。

什么是 BOM

BOM:Browser Object Model,浏览器对象模型。

BOM 的结构图:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图16

从上图也可以看出:

  • window 对象是 BOM 的顶层(核心)对象,所有对象都是通过它延伸出来的,也可以称为 window 的子对象。
  • DOM 是 BOM 的一部分。

window 对象:

  • window 对象是 JavaScript 中的顶级对象。
  • 全局变量、自定义函数也是 window 对象的属性和方法。
  • window 对象下的属性和方法调用时,可以省略 window。

下面讲一下 BOM 的常见内置方法和内置对象。

弹出系统对话框

比如说,alert(1)是 window.alert(1)的简写,因为它是 window 的子方法。

系统对话框有三种:

alert(); //不同浏览器中的外观是不一样的

confirm(); //兼容不好

prompt(); //不推荐使用

confirm 举例

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图17

如果点击确定,查看 console。输出 true,否则为 false

那么就可以进行相应的操作了。默认的页面无法修改,你认为它丑也没有办法。

一般用模态框来做,可以自定义。

打开窗口、关闭窗口

1、打开窗口:

window.open(url,target);

参数解释:

  • url:要打开的地址。
  • target:新窗口的位置。可以是:_blank、_self、 _parent 父框架。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>


<!--行间的js中的open() window不能省略-->
<button onclick="window.open('https://www.luffycity.com/')">路飞学城</button>


<button>打开百度</button>
<!--强制关闭-->
<button onclick="window.close()">关闭</button>
<!--有提示框的关闭-->
<button>关闭</button>


</body>
<script type="text/javascript">


    var oBtn = document.getElementsByTagName('button')[1];  //强制关闭的按钮
    var closeBtn = document.getElementsByTagName('button')[3];  //带提示框的关闭按钮


    oBtn.onclick = function(){
        //open('https://www.baidu.com')


        //打开空白页面
        open('about:blank',"_self")
    }
    closeBtn.onclick = function(){
        if(confirm("是否关闭?")){
            close();
        }
    }


</script>
</html>

默认是_blank,表示新窗口打开。

访问网页,点击按钮,就可以跳转网页了

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图18

阻止 a 标签跳转有 2 个方法

1.使用 javascript:;

<a href="javascript:;">百度</a>

2.使用 js 的 preventDefault 方法

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>


<a href="http://www.baidu.com" id="baidu">百度</a>


</body>
<script type="text/javascript">
    var baidu = document.getElementById('baidu');
    //绑定点击事件
    baidu.onclick = function (e) {
        //阻止a标签的默认跳转
        e.preventDefault();
        //跳转到淘宝页面
        window.open('http://www.taobao.com')
    }
</script>
</html>

访问网页,点击百度,就会跳转到指定页面,比如淘宝

location 对象

location 只做了解

window.location 可以简写成 location。location 相当于浏览器地址栏,可以将 url 解析成独立的片段。

location 对象的属性

  • href:跳转
  • hash 返回 url 中#后面的内容,包含#
  • host 主机名,包括端口
  • hostname 主机名
  • pathname url 中的路径部分
  • protocol 协议 一般是 http、https
  • search 查询字符串

location.href 属性举例:

举例 1:点击盒子时,进行跳转。

<body>
<div>smyhvae</div>
<script>


    var div = document.getElementsByTagName("div")[0];


    div.onclick = function () {
        location.href = "http://www.baidu.com";   //点击div时,跳转到指定链接
 //     window.open("http://www.baidu.com","_blank");  //方式二
    }


</script>
</body>

举例 2:5 秒后自动跳转到百度。

有时候,当我们访问一个不存在的网页时,会提示 5 秒后自动跳转到指定页面,此时就可以用到 location。举例:

<script>

    setTimeout(function () {
        location.href = "http://www.baidu.com";
    }, 5000);
</script>

如果使用 file:///C:/Users/xiao/bom.html这种方式访问时 ,是无法获取 host,hostname,pathname…这些属性的

使用 Pycharm 或者 webstom,它自带有一个 web 服务器,那么就可以得到这些信息

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script type="text/javascript">
        console.log(location.host);
        console.log(location.hostname);
        console.log(location.pathname);
        console.log(location.protocol);
        console.log(location.search);
    </script>
</body>
</html>

访问网页,查看 console

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图19

location 对象的方法

location.reload():重新加载

setTimeout(function(){
         //3秒之后让网页整个刷新
    window.location.reload();


},3000)

这个方法很少用,一般会用到局部刷新,后面的 django 课程会讲到

navigator 对象

window.navigator 的一些属性可以获取客户端的一些信息。

  • userAgent:系统,浏览器)
  • platform:浏览器支持的系统,win/mac/linux

例子:

console.log(navigator.userAgent);
console.log(navigator.platform);

查看网页 console

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图20

userAgent 这个是很重要,爬虫会用到它,以及后面的 B/S 架构

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图21

查看请求头

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图22

history 对象

1、后退:

  • history.back()history.go(-1):0 是刷新

2、前进:

  • history.forward()
  • history.go(1)

用的不多。因为浏览器中已经自带了这些功能的按钮

五、client、offset、scroll 系列

1.client 系列

代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        .box{
            width: 200px;
            height: 200px;
            position: absolute;
            border: 10px solid red;
            /*margin: 10px 0px 0px 0px;*/
            padding: 80px;
        }
    </style>
</head>
<body>
<div class="box">
    哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
</div>
</body>
<script type="text/javascript">
    /*
     *   clientTop 内容区域到边框顶部的距离 ,说白了,就是边框的高度
     *      clientLeft 内容区域到边框左部的距离,说白了就是边框的乱度
     *      clientWidth 内容区域+左右padding   可视宽度
     *      clientHeight 内容区域+ 上下padding   可视高度
     * */


    var oBox = document.getElementsByClassName('box')[0];
    console.log(oBox.clientTop);
    console.log(oBox.clientLeft);
    console.log(oBox.clientWidth);
    console.log(oBox.clientHeight);


</script>


</html>

这些属性是在 dom 操作的,client 用的不是很多

内容区域是包含 padding 的,父相子绝无视 padding

访问网页:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图23

查看 console

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图24

2.屏幕的可视区域

这个很少用

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
</body>
<script type="text/javascript">
    // 屏幕的可视区域
    window.onload = function(){
        // document.documentElement 获取的是html标签
        console.log(document.documentElement.clientWidth);
        console.log(document.documentElement.clientHeight);
        // 窗口大小发生变化时,会调用此方法
        window.onresize = function(){
            console.log(document.documentElement.clientWidth);
            console.log(document.documentElement.clientHeight);
        }
    }
</script>
</html>

查看 console。将网页窗口方法,缩小时,console 里面的数值,会发生变化。

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图25

3.offset 系列

offset 表示偏移,这个是重点,用的比较多。

代码如下,注释都挺清楚的

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
        </style>

    </head>
    <body style="height: 2000px">
        <div>
            <div class="wrap" style=" width: 300px;height: 300px;background-color: green">
                <div id="box" style="width: 200px;height: 200px;border: 5px solid red;position: absolute;top:50px;left: 30px;">            
                </div>
            </div>
        </div>
    </body>
    <script type="text/javascript">
        window.onload = function(){
            var box = document.getElementById('box')
            /*
             offsetWidth占位宽  内容+padding+border
             offsetHeight占位高 
             * offsetTop: 如果盒子没有设置定位 到body的顶部的距离,如果盒子设置定位,那么是以父辈为基准的top值
             * offsetLeft: 如果盒子没有设置定位 到body的左部的距离,如果盒子设置定位,那么是以父辈为基准的left值

             * */
            console.log(box.offsetTop)
            console.log(box.offsetLeft)
            console.log(box.offsetWidth)
            console.log(box.offsetHeight)

        }

    </script>
</html>

访问网页

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图26

查看 console

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图27

4.scroll 系列

scroll 表示滚动,这个用的也比较多

代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        *{padding: 0;margin: 0;}
    </style>
</head>
<body style="width: 2000px;height: 2000px;">
<div style="height: 200px;background-color: red;"></div>
<div style="height: 200px;background-color: green;"></div>
<div style="height: 200px;background-color: yellow;"></div>
<div style="height: 200px;background-color: blue;"></div>
<div style="height: 200px;background-color: gray;"></div>
<div id = 'scroll' style="width: 200px;height: 200px;border: 1px solid red;overflow: auto;padding: 10px;margin: 5px 0px 0px 0px;">
    <p>路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城
        路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城
        路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城
        路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城路飞学城
    </p>


</div>


</body>
<script type="text/javascript">
    window.onload = function(){
        //实施监听滚动事件
        window.onscroll = function(){
           console.log('上'+document.documentElement.scrollTop)
           console.log('左'+document.documentElement.scrollLeft)
           console.log('宽'+document.documentElement.scrollWidth)
           console.log('高'+document.documentElement.scrollHeight)
        }


        var s = document.getElementById('scroll');


        s.onscroll = function(){
//            scrollHeight : 内容的高度+padding  不包含边框
            console.log('上'+s.scrollTop)
            console.log('左'+s.scrollLeft)
            console.log('宽'+s.scrollWidth)
            console.log('高'+s.scrollHeight)
        }
    }


</script>
</html>

查看网页:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图28

只要滚动窗口,console 的数值,就会发生变化。小窗口的进度条,拉动,也会发生变化

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图29

今日作业,淘宝的滚动监听

当精度条,拉到指定位置时。出现搜索框,它的位置是固定的,并且覆盖页面内容。

需要用到 scroll

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图30

思路:

实时监听当前页面的页面滚动事件,使用 window.onscroll

获取滚动条位置,使用 document.documentElement.scrollTop

当滚动条位置大于等于 150 时,设置搜索框对应的属性,让它能够固定,使用 position: fixed 加上 z-index:999

代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        * {
            padding: 0;
            margin: 0;
        }


        ul {
            list-style: none;
        }
        .nav {
            width: 100%;
            height: 40px;
            background-color: purple;
            /*position: fixed;*/
            top: 0;
            left: 0;
            /*z-index: 99999;*/
        }


        .wrap {
            width: 960px;
            overflow: hidden;
            margin: 0px auto;
            background-color: purple;
            border-radius: 5px;


        }


        .wrap ul li {
            float: left;
            width: 160px;
            height: 20px;
            line-height: 40px;
            text-align: center;
        }


        .wrap ul li a {
            width: 160px;
            height: 40px;
            display: block;
            color: white;
            font-size: 14px;
            text-decoration: none;
        }


        .wrap ul li a:hover {
            background: yellow;
            color: green;
            text-decoration: underline;
        }


        .pass-text-input {
            height: 16px;
            padding: 11px 10px;
            margin-right: 10px;
            border: 1px solid #ddd;
            font-size: 14px;
            color: #666;
        }
        .text-input-length{
            width: 328px;
        }
        .pass-label {
            #display: block;
            #float: left;
            height: 42px;
            width: 65px;
            margin-right: 10px;
            line-height: 42px;
            font-size: 14px;
            color: #666;
            font-weight: 700;
            text-align: right;
        }
        /*默认样式*/
        .inp_default {
            text-align: center;background-color: #2ae0c8;z-index: 999;
        }
        /*居中样式*/
        .inp_center {
            margin-top: -50px;text-align: center;background-color: rgb(255,85,0);z-index: 999;position: fixed;width: 100%;
        }
    </style>
</head>
<body>




<div id = 'scroll'>
    <div class="nav">
        <div class="wrap">
            <ul>
                <li>
                    <a href="#">天猫</a>
                </li>
                <li>
                    <a href="#">聚划算</a>
                </li>
                <li>
                    <a href="#">天猫超市</a>
                </li>
                <li>
                    <a href="#">淘抢购</a>
                </li>
                <li>
                    <a href="#">电器城</a>
                </li>
                <li>
                    <a href="#">司法拍卖</a>
                <li>
            </ul>
        </div>
    </div>


    <div style="text-align: center;width: 100%">
        <div id="search" class="inp_default">
            <p>
                <label class="pass-label left">宝贝</label>
                <input type="text" name="userName" class="pass-text-input text-input-length left" placeholder="请输入搜索文字">
                <label class="pass-label left">搜索</label>
            </p>
        </div>
        <div style="height: 10px"></div>
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <!--<p>哈哈哈哈哈哈哈哈</p>-->
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
        <img src="images/zly.jpg" alt="">
    </div>
</div>


</body>
<script type="text/javascript">
    window.onload = function(){
        var search = document.getElementById('search');  //搜索框
        //实时监听当前页面的页面滚动事件
        window.onscroll = function(){
            console.log('上'+document.documentElement.scrollTop);  //获取滚动条位置
            // console.log('左'+document.documentElement.scrollLeft);
            // console.log('宽'+document.documentElement.scrollWidth);
            // console.log('高'+document.documentElement.scrollHeight);
            //当滚动条位置大于等于150时
            if (document.documentElement.scrollTop >= 150){
                // alert('到了150');
                search.className = "inp_center";  //设置class属性
            }else {
                search.className = "inp_default";  //默认样式
            }
        }
    }


</script>
</html>

网页效果:

Day52 关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列 - 图31