今日学习任务

  • [ ] 1.案例拖拽盒子

  • [ ] (1)拖拽事件流程

  • (2)拖拽盒子原理
  • (3)案例:拖拽登陆框
  • 2.阻止a标签默认跳转两种常用方式
  • 3.注册/移除多个同名事件(addEventListener)
  • [ ] 4.事件冒泡

  • [ ] (1)事件冒泡介绍

  • (2)事件冒泡利用(事件委托)
  • (3)事件冒泡影响
  • (4)阻止事件冒泡
  • [ ] 5.事件捕获

  • [ ] (1)事件捕获介绍

  • (2)事件三个阶段
  • [ ] 6.事件对象补充属性

  • [ ] (1)事件类型type

  • (2)键盘事件与获取按键

01-案例:拖拽盒子

1.1-拖拽盒子01

day07 - 图1

思路分析

day07 - 图2

本小节知识点:鼠标拖拽

  • 复习鼠标事件:

    • onclick:鼠标点下去并且弹起来触发(单击一次)
    • ondblclick:鼠标连续点击两次(双击)
    • onmousedown:鼠标按下就触发
    • onmouseup: 鼠标弹起触发
    • onmouseover:鼠标移入
    • onmouseout:鼠标移出
    • onmousemove:鼠标移动
  • 鼠标拖拽:(1)先按下 (2)然后移动 (3)最后松开
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. #father {
  8. width: 200px;
  9. height: 400px;
  10. background-color: skyblue;
  11. position: absolute;
  12. top: 0px;
  13. left: 0px;
  14. }
  15. #son {
  16. width: 200px;
  17. height: 100px;
  18. background-color: hotpink;
  19. cursor: move;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div id="father">
  25. <div id="son"></div>
  26. </div>
  27. <script>
  28. /*
  29. 复习鼠标事件
  30. 鼠标单击:onclick 按下+松开 = 单击一次
  31. 鼠标双击:ondblclick
  32. 鼠标移入:onmouseover
  33. 鼠标移出:onmouseout
  34. 鼠标移动:onmousemove
  35. 鼠标按下: onmousedown
  36. 鼠标松开: onmouseup
  37. 拖拽事件
  38. 1.鼠标按下 : 给元素注册
  39. 2.鼠标移动 : (1)给页面注册 (2)需要在按下的事件处理中注册
  40. 3.鼠标松开 : 在按下事件处理中注册
  41. */
  42. let son = document.getElementById('son');// 与父元素对其 offsetLeft:0
  43. let father = document.getElementById('father');// 父元素 offsetLeft:到body的距离
  44. // son.onclick = function(){
  45. // console.log('鼠标单击');
  46. // };
  47. //1.鼠标按下
  48. son.onmousedown = function (e) {
  49. //1级链
  50. console.log('鼠标按下了');
  51. //1.鼠标按下:求蓝线 = 红线(e.pageX) - 绿线(father.offsetLeft)
  52. let x = e.pageX - father.offsetLeft;
  53. let y = e.pageY - father.offsetTop;
  54. //2.鼠标移动
  55. document.onmousemove = function (e) {
  56. //2级链
  57. //2.求黑线 = 红线(e.pageX) - 蓝线
  58. father.style.left = e.pageX - x + 'px';
  59. father.style.top = e.pageY - y + 'px';
  60. // console.log('鼠标移动');
  61. // console.log(e);
  62. };
  63. //3.鼠标松开
  64. //鼠标松开也可以在按下之后注册:因为如果鼠标没有按下,不可能触发松开事件
  65. son.onmouseup = function () {
  66. console.log('鼠标松开');
  67. //移除鼠标移动事件
  68. document.onmousemove = null;
  69. };
  70. };
  71. </script>
  72. </body>
  73. </html>

1.2-拖拽盒子02(元素有margin)

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. #father {
  8. width: 200px;
  9. height: 400px;
  10. background-color: skyblue;
  11. position: absolute;
  12. top: 0px;
  13. left: 0px;
  14. margin: 50px;
  15. }
  16. #son {
  17. width: 200px;
  18. height: 100px;
  19. background-color: hotpink;
  20. cursor: move;
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <div id="father">
  26. <div id="son"></div>
  27. </div>
  28. <script>
  29. /*
  30. 复习鼠标事件
  31. 鼠标单击:onclick 按下+松开 = 单击一次
  32. 鼠标双击:ondblclick
  33. 鼠标移入:onmouseover
  34. 鼠标移出:onmouseout
  35. 鼠标移动:onmousemove
  36. 鼠标按下: onmousedown
  37. 鼠标松开: onmouseup
  38. 拖拽事件
  39. 1.鼠标按下 : 给元素注册
  40. 2.鼠标移动 : (1)给页面注册 (2)需要在按下的事件处理中注册
  41. 3.鼠标松开 : 在按下事件处理中注册
  42. */
  43. let son = document.getElementById('son');// 与父元素对其 offsetLeft:0
  44. let father = document.getElementById('father');// 父元素 offsetLeft:到body的距离
  45. // son.onclick = function(){
  46. // console.log('鼠标单击');
  47. // };
  48. /*发现问题:为什么元素添加margin之后,拖拽会有顿闪效果
  49. 分析问题: 元素定位是按照margin左上角来定位
  50. 解决问题: 如果元素有margin,则应该减去margin
  51. */
  52. //1.鼠标按下
  53. son.onmousedown = function (e) {
  54. //1级链
  55. console.log('鼠标按下了');
  56. //1.鼠标按下:求蓝线 = 红线(e.pageX) - 绿线(father.offsetLeft)
  57. let x = e.pageX - father.offsetLeft;
  58. let y = e.pageY - father.offsetTop;
  59. //2.鼠标移动
  60. document.onmousemove = function (e) {
  61. //2级链
  62. //2.求黑线 = 红线(e.pageX) - 蓝线
  63. father.style.left = e.pageX - x - 50 + 'px';
  64. father.style.top = e.pageY - y -50 + 'px';
  65. // console.log('鼠标移动');
  66. // console.log(e);
  67. };
  68. //3.鼠标松开
  69. //鼠标松开也可以在按下之后注册:因为如果鼠标没有按下,不可能触发松开事件
  70. son.onmouseup = function () {
  71. console.log('鼠标松开');
  72. //移除鼠标移动事件
  73. document.onmousemove = null;
  74. };
  75. };
  76. </script>
  77. </body>
  78. </html>

1.3-案例:拖拽登录验证

day07 - 图3

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <style>
  9. .wrap {
  10. width: 360px;
  11. height: 180px;
  12. margin: 50px auto;
  13. border: 1px solid black;
  14. position: relative;
  15. }
  16. .wrap .icon {
  17. position: absolute;
  18. left: 0;
  19. top: 60px;
  20. }
  21. .wrap .progress {
  22. width: 100%;
  23. height: 40px;
  24. position: relative;
  25. top: -4px;
  26. background-color: pink;
  27. }
  28. .cube {
  29. position: absolute;
  30. width: 40px;
  31. height: 40px;
  32. background-color: red;
  33. cursor: pointer;
  34. }
  35. .bar {
  36. position: absolute;
  37. width: 0px;
  38. height: 40px;
  39. background-color: green;
  40. }
  41. </style>
  42. </head>
  43. <body>
  44. <div class="wrap">
  45. <img src="./images/drag01.png" alt="">
  46. <img class="icon" src="./images/drag02.png" alt="">
  47. <div class="progress">
  48. <div class="bar"></div>
  49. <div class="cube"></div>
  50. </div>
  51. </div>
  52. <script>
  53. /*
  54. 1.分析需求(交互):
  55. 拖拽小方块cube :
  56. a. cube小方块 水平移动
  57. b. bar进度条变宽
  58. c. icon小图片对应(移动距离一致)水平移动
  59. d. 检测icon小图片位置是否正确
  60. 2.思路分析(事件三要素)
  61. 获取元素:事件源:
  62. 注册事件:事件类型
  63. 事件处理:
  64. */
  65. //1.获取元素
  66. let wrap = document.querySelector('.wrap');
  67. let cube = document.querySelector('.cube');
  68. let bar = document.querySelector('.bar');
  69. let icon = document.querySelector('.icon');
  70. //2.注册拖拽事件
  71. //(1)注册鼠标按下
  72. cube.onmousedown = function (e) {
  73. e = e || window.event;
  74. //记录鼠标按下时的 e.pageX
  75. let x = e.pageX;
  76. //(2)注册鼠标移动:页面
  77. document.onmousemove = function (e) {
  78. e = e || window.event;
  79. //a. 蓝线距离 = 鼠标移动e.pageX - 鼠标按下e.pageX
  80. let x1 = e.pageX - x;
  81. //b. 边界检测
  82. x1 = x1 <= 0 ? 0 : x1;
  83. /* 最大位移 = 父盒子宽度 - 小方块宽度 */
  84. let maxLeft = wrap.offsetWidth - cube.offsetWidth;
  85. x1 = x1 >= maxLeft ? maxLeft : x1;
  86. //c. 小方块移动
  87. cube.style.left = x1 + 'px';
  88. //d. 进度条变宽
  89. bar.style.width = x1 + 'px';
  90. //e. 小图标对应移动
  91. icon.style.left = x1 + 'px';
  92. };
  93. //(3)注册鼠标松开
  94. document.onmouseup = function () {
  95. //移除鼠标移动
  96. document.onmousemove = null;
  97. //检测小图标位置是否正确
  98. if(icon.offsetLeft > 150 && icon.offsetLeft < 160){
  99. alert('验证成功,即将跳转登录页');
  100. //刷新页面
  101. window.location.href = 'http://www.itheima.com';
  102. }else{
  103. alert('验证失败,请重新验证');
  104. //刷新页面
  105. window.location.reload();
  106. }
  107. };
  108. };
  109. </script>
  110. </body>
  111. </html>

02-阻止a标签默认跳转

1.1-阻止a标签跳转两种常用方式

  • 默认情况下,点击a标签会跳转到一个新的网页,这叫做超链接
  • 某些情况下,我们只希望拿到a标签的样式(鼠标放上去有小手,用户很直观的知道这可以点击),而不希望跳转到新的网页这个时候我们就可以阻止a标签的跳转
  • 以下几种不需要死记硬背,实际开发习惯任何一种即可

    • 原理了解即可:

      • 第一种:给a标签添加点击事件,在点击事件中return false(建议使用,用于任意跳转a标签)
      • 第二种:给a标签的href属性设置一个伪链接(一般不用,用于页内跳转的a标签)
    • 课外拓展

      • 打电话:tel:
      • 发邮件:mailto:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <!--默认情况下,点击a标签会跳转到一个新的网页,这叫做超链接
  9. 某些情况下,我们只希望拿到a标签的样式(鼠标放上去有小手,用户很直观的知道这可以点击),而不希望跳转到新的网页
  10. 这个时候我们就可以阻止a标签的跳转
  11. 以下几种不需要死记硬背,实际开发习惯任何一种即可
  12. * 原理了解即可:第一种:给a标签添加点击事件,在点击事件中return false
  13. 第二种:给a标签的href属性设置一个伪链接
  14. -->
  15. <!--行内写法-->
  16. <a href="#" target="_blank" onclick="alert('哈哈,有SB点击我了');return false;">跳转1</a>
  17. <!--注意:只要是行内写法,就需要在行内return false-->
  18. <a href="#" target="_blank" onclick="test1();return false;">跳转2</a>
  19. <!--内联写法,直接在函数中return false即可-->
  20. <a href="#" target="_blank" id="link">跳转3</a>
  21. <!--设置href属性伪链接:主要此时不要使用target='_blank',要不然无效-->
  22. <a href="javascript:void(0)">跳转4</a>
  23. <a href="javascript:;">跳转5</a>
  24. </body>
  25. <script>
  26. function test1 ( ) {
  27. alert('今晚');
  28. }
  29. let link = document.getElementById('link');
  30. link.onclick = function ( ) {
  31. alert('大吉');
  32. return false;
  33. }
  34. </script>
  35. </html>

1.2-案例:页面换肤

day07 - 图4

需求:点击上方小图,下方展示对应大图

  • 思路:

    • 1.将图片的路径放入a标签的href属性中,并且禁用a标签的默认跳转
    • 2.给每一个a标签添加点击事件
    • 3.点击时,取出本次点击的a标签的href属性的值,赋值给下方大图的src属性
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. .small {
  8. width: 180px;
  9. }
  10. li {
  11. float: left;
  12. list-style: none;
  13. margin-right: 20px;
  14. }
  15. ul {
  16. width: 1000px;
  17. margin: 0 auto;
  18. height: 160px;
  19. }
  20. .father {
  21. width: 1000px;
  22. margin: 0 auto;
  23. }
  24. .father #bigPic {
  25. width: 1000px;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <ul id="ul1">
  31. <li><a href="images/01.jpg"><img src="images/01.jpg" alt="" class="small"/></a></li>
  32. <li><a href="images/02.jpg"><img src="images/02.jpg" alt="" class="small"/></a></li>
  33. <li><a href="images/03.jpg"><img src="images/03.jpg" alt="" class="small"/></a></li>
  34. <li><a href="images/04.jpg"><img src="images/04.jpg" alt="" class="small"/></a></li>
  35. <li><a href="images/05.jpg"><img src="images/05.jpg" alt="" class="small"/></a></li>
  36. </ul>
  37. <div class="father">
  38. <img src="images/01.jpg" alt="" id="bigPic"/>
  39. </div>
  40. <script>
  41. /*
  42. 1.分析需求(交互):点击上方a标签:取出a标签中img元素的src属性赋值给下方大图的src
  43. 2.思路分析(事件三要素)
  44. 获取元素:事件源:
  45. 注册事件:事件类型
  46. 事件处理:
  47. */
  48. //1.获取元素
  49. let aList = document.querySelectorAll('a');
  50. let bigPic = document.querySelector('#bigPic')
  51. //2.注册事件
  52. for(let i = 0;i<aList.length;i++){
  53. aList[i].onclick = function(){
  54. //3.事件处理:取出a标签中img元素的src属性赋值给下方大图的src
  55. console.log(this);
  56. //第一种方式:通过children取出a标签子元素img标签的src属性值
  57. //bigPic.src = this.children[0].src;
  58. //另一种方式:一旦阻止a标签默认跳转。href属性失效,但是可以用来存储自定义数据
  59. bigPic.src = this.href;
  60. return false;
  61. };
  62. };
  63. </script>
  64. </body>
  65. </html>

03-注册/移除多个同名事件(addEventListener)

1.1-addEventListener注册事件

  • 本小节知识点:如何给一个元素添加多个相同事件
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <input type="button" value="点我" id="btn"/>
  9. </body>
  10. </html>
  11. <script>
  12. /*本小节知识点:如何给一个元素添加多个相同事件
  13. */
  14. let btn = document.getElementById ( "btn" )
  15. //用这样的方式添加相同的事件,后面的会覆盖前面的
  16. // btn.onclick = function () {
  17. //
  18. // alert("点一次200块");
  19. // }
  20. //
  21. // btn.onclick = function () {
  22. //
  23. // alert("点我干啥?");
  24. // }
  25. //可以给同名的事件,绑定多个事件处理程序
  26. //语法:对象.addEventListener(参数1,参数2,参数3);
  27. //参数1:事件名(字符串),不要加on 例如:click 、 mouseover 、mouseout
  28. //参数2:事件处理程序(函数名),当事件触发后哪个函数来处理
  29. //参数3:是一个bool类型,可以不传,默认为fasle(代表冒泡)跟冒泡和捕获有关
  30. //如果有同名事件不会覆盖,而是会依次执行
  31. //IE8及以前的版本不支持
  32. /*
  33. btn.addEventListener ( "click", function ( e ) {
  34. e = e || window.event
  35. alert ( "嘿嘿嘿" )
  36. console.log ( e )
  37. }, false )
  38. btn.addEventListener ( "click", function () {
  39. alert ( "哈哈哈" )
  40. } )
  41. //如果传入已经存在的函数,那么直接写函数名,千万不要写小括号
  42. btn.addEventListener ( "click", sayHi, false )
  43. function sayHi ( e ) {
  44. e = e || window.event
  45. alert ( "你来追我呀!" )
  46. console.log ( e )
  47. }
  48. */
  49. //只有IE8以前支持的方法,其他的都不支持
  50. //只有2个参数
  51. //参数1:事件名(字符串),但是要加on
  52. //参数2:事件处理程序。事件触发时哪个函数来响应
  53. //后面的先执行,前面的后执行
  54. /*
  55. btn.attachEvent("onclick", function () {
  56. alert("祝中间的早晚偷情成功");
  57. });
  58. btn.attachEvent("onclick", function () {
  59. alert("祝隔壁老王和我隔壁的幸福");
  60. });
  61. */
  62. /*兼容性封装*/
  63. /** 给元素添加多个相同的事件
  64. * @param obj:元素 eventName:事件名 fn:事件处理函数
  65. * @return 无
  66. */
  67. function addEvent(obj, eventName, fn) {
  68. //能力检测
  69. if (obj.addEventListener) { //非IE8
  70. obj.addEventListener(eventName, fn);
  71. } else if (obj.attachEvent) { //IE8
  72. obj.attachEvent("on" + eventName, fn);
  73. } else { //默认方式
  74. obj["on" + eventName] = fn;
  75. }
  76. }
  77. </script>

1.2-removeEventListener移除事件

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title>标题</title>
  6. </head>
  7. <body>
  8. <input type="button" value="按钮" id="btn"/>
  9. <script>
  10. let btn = document.getElementById("btn");
  11. //1.on+事件名称的方式
  12. // btn.onclick = function () {
  13. // alert("哈哈");
  14. // btn.onclick = null; //移除事件。
  15. // }
  16. //2.元素名.addEventListener注册的事件,移除方式
  17. //元素名.removeEventListener(参数1,参数2,参数3);
  18. //参数1:事件名称
  19. //参数2:事件处理程序
  20. //参数3:布尔类型的值
  21. // function test() {
  22. // alert("哈哈");
  23. // }
  24. // btn.addEventListener("click", test,false);
  25. // btn.removeEventListener("click",test,false)
  26. //3.元素名.attachEvent注册的事件移除方式
  27. //元素名.detachEvent(参数1,参数2)
  28. //参数1:事件名称 是加了on的方式
  29. //参数2:事件处理程序。
  30. // function test2(){
  31. // alert("哈哈哈哈哈哈啊....");
  32. // }
  33. // btn.attachEvent("onclick",test2);
  34. // btn.detachEvent("onclick",test2);
  35. //4.移除事件,不同的添加方式,使用不同的方式移除,所以要做兼容处理。
  36. function removeEventListener(obj,type,listener){
  37. //能力检测
  38. if(obj.removeEventListener){
  39. obj.removeEventListener(type,listener,false);
  40. }else if(obj.detachEvent){
  41. obj.detachEvent("on"+type,listener);
  42. }else {
  43. obj["on"+type] = null;
  44. }
  45. }
  46. //5.对封装的函数做一个测试
  47. function ceshi(){
  48. alert("呵呵呵嘻嘻嘻嘻....cs移出事件函数....");
  49. }
  50. addEventListener(btn,"click",ceshi);
  51. removeEventListener(btn,"click",ceshi);
  52. //4.给某一个元素注册多个相同的事件,不同的浏览器有不同的方式,所以要做兼容。
  53. function addEventListener(obj,type,listener){
  54. //能力检测
  55. if(obj.addEventListener){
  56. obj.addEventListener(type,listener,false);
  57. }else if(obj.attachEvent){
  58. obj.attachEvent("on"+type,listener);
  59. }else {
  60. obj["on"+type] = listener;
  61. }
  62. }
  63. </script>
  64. </body>
  65. </html>

04-事件冒泡

1.1-事件冒泡介绍

本小节知识点:介绍什么是事件冒泡

  • 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发

    • 元素->父元素->body->html->document->window

      • 事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. #box{
  8. width: 300px;
  9. height: 300px;
  10. background-color: hotpink;
  11. position: relative;
  12. }
  13. #son{
  14. width: 100px;
  15. height: 100px;
  16. position: absolute;
  17. left: 350px;
  18. top: 350px;
  19. background-color: yellowgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div id="box">
  25. <input type="button" value="点我" id="btn"/>
  26. <div id="son"></div>
  27. </div>
  28. </body>
  29. </html>
  30. <script>
  31. /*本小节知识点:介绍什么是事件冒泡
  32. * 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发
  33. * 元素->父元素->body->html->window
  34. *事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
  35. */
  36. window.onclick = function () {
  37. alert("window被点击了");
  38. }
  39. document.onclick = function () {
  40. alert("文档被点击了");
  41. }
  42. document.documentElement.onclick = function () {
  43. alert("html被点击了");
  44. }
  45. document.body.onclick = function () {
  46. alert("body被点击了");
  47. }
  48. document.getElementById("box").onclick = function () {
  49. alert("我是骚粉的大盒子");
  50. };
  51. document.getElementById("btn").onclick = function () {
  52. alert("我是小按钮");
  53. };
  54. document.getElementById("son").onclick = function () {
  55. alert("我是又黄又绿的小盒子");
  56. };
  57. </script>

1.2-事件冒泡利用(事件委托)

本小节知识点:介绍事件冒泡的好处

  1. 事件冒泡好处:如果想给父元素的多个子元素添加事件,我们可以只需要给父元素添加事件即可,然后

通过获取事件源(e.target)就可以得知是哪一个子元素触发了这个事件

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <ul id="ul1">
  9. <li>隔壁老王1</li>
  10. <li>隔壁老王2</li>
  11. <li>隔壁老王3</li>
  12. <li>隔壁老王4</li>
  13. <li>隔壁老王5</li>
  14. </ul>
  15. </body>
  16. </html>
  17. <script>
  18. /*本小节知识点:介绍事件冒泡的好处
  19. 事件冒泡好处:如果想给父元素的多个子元素添加事件,我们可以只需要给父元素添加事件即可,然后
  20. 通过获取事件源(e.target)就可以得知是哪一个子元素触发了这个事件
  21. */
  22. let ul = document.getElementById("ul1");
  23. //1.如果想给ul中的每一个li标签添加点击事件,以前的做法需要遍历ul的li标签逐个添加
  24. // for (let i = 0; i < ul.children.length; i++) {
  25. //
  26. // ul.children[i].onclick = function () {
  27. //
  28. // alert(this.innerHTML);
  29. // }
  30. // }
  31. //2.使用时间冒泡:只需要给父元素添加点击事件即可
  32. ul.onclick = function (e) {
  33. e = e || window.event;
  34. let target = e.target || e.srcElement;
  35. console.log(target.innerHTML);
  36. //target:事件源:触发本次事件的源头
  37. alert(e.target.innerHTML);
  38. }
  39. </script>

1.3-事件冒泡影响

  • 本小节知识点:介绍事件冒泡的影响

    • 事件冒泡会导致需求冲突:例如我想要添加一个功能,弹出登录窗之后点击body空白区域让登陆窗消失
    • 此时a标签弹出登录窗的点击事件会触发body的点击事件,导致登陆窗一出来就消失
  • 解决方案:阻止事件冒泡(下一小节知识点)
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. .login-header {
  8. width: 100%;
  9. text-align: center;
  10. height: 30px;
  11. font-size: 24px;
  12. line-height: 30px;
  13. }
  14. html, body, ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a {
  15. padding: 0px;
  16. margin: 0px;
  17. }
  18. .login {
  19. width: 512px;
  20. position: absolute;
  21. border: #ebebeb solid 1px;
  22. height: 280px;
  23. left: 50%;
  24. right: 50%;
  25. background: #ffffff;
  26. box-shadow: 0px 0px 20px #ddd;
  27. z-index: 9999;
  28. margin-left: -256px;
  29. margin-top: 140px;
  30. display: none;
  31. }
  32. .login-title {
  33. width: 100%;
  34. margin: 10px 0px 0px 0px;
  35. text-align: center;
  36. line-height: 40px;
  37. height: 40px;
  38. font-size: 18px;
  39. position: relative;
  40. cursor: move;
  41. }
  42. .login-input-content {
  43. margin-top: 20px;
  44. }
  45. .login-button {
  46. width: 50%;
  47. margin: 30px auto 0px auto;
  48. line-height: 40px;
  49. font-size: 14px;
  50. border: #ebebeb 1px solid;
  51. text-align: center;
  52. }
  53. .login-bg {
  54. width: 100%;
  55. height: 100%;
  56. position: fixed;
  57. top: 0px;
  58. left: 0px;
  59. background: #000000;
  60. opacity: 0.3;
  61. display: none;
  62. }
  63. a {
  64. text-decoration: none;
  65. color: #000000;
  66. }
  67. .login-button a {
  68. display: block;
  69. }
  70. .login-input input.list-input {
  71. float: left;
  72. line-height: 35px;
  73. height: 35px;
  74. width: 350px;
  75. border: #ebebeb 1px solid;
  76. text-indent: 5px;
  77. }
  78. .login-input {
  79. overflow: hidden;
  80. margin: 0px 0px 20px 0px;
  81. }
  82. .login-input label {
  83. float: left;
  84. width: 90px;
  85. padding-right: 10px;
  86. text-align: right;
  87. line-height: 35px;
  88. height: 35px;
  89. font-size: 14px;
  90. }
  91. .login-title span {
  92. position: absolute;
  93. font-size: 12px;
  94. right: -20px;
  95. top: -30px;
  96. background: #ffffff;
  97. border: #ebebeb solid 1px;
  98. width: 40px;
  99. height: 40px;
  100. border-radius: 20px;
  101. }
  102. </style>
  103. </head>
  104. <body>
  105. <div class="login-header">
  106. <a id="link" href="javascript:void(0);">点击,弹出登录框</a>
  107. </div>
  108. <div id="login" class="login">
  109. <div id="title" class="login-title">登录会员
  110. <span>
  111. <a id="closeBtn" href="javascript:void(0);" class="close-login"> 关闭</a>
  112. </span>
  113. </div>
  114. <div class="login-input-content">
  115. <div class="login-input">
  116. <label>用户名:</label>
  117. <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
  118. </div>
  119. <div class="login-input">
  120. <label>登录密码:</label>
  121. <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
  122. </div>
  123. </div>
  124. <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
  125. </div>
  126. <div id="bg" class="login-bg"></div>
  127. <script src="common.js"></script>
  128. <script>
  129. /*本小节知识点:介绍事件冒泡的影响
  130. 事件冒泡会导致需求冲突:例如我想要添加一个功能,弹出登录窗之后点击body空白区域让登陆窗消失
  131. 此时a标签弹出登录窗的点击事件会触发body的点击事件,导致登陆窗一出来就消失
  132. 解决方案:阻止事件冒泡(下一小节知识点)
  133. */
  134. //找到弹出窗口的a标签
  135. let open = document.getElementById("link");//点击弹出登录窗口
  136. //找到整个登录窗口
  137. let login = document.getElementById("login");//需要移动
  138. //找到背景阴影
  139. let bg = document.getElementById("bg");//弹出登录窗后需要修改颜色
  140. //找到登录的标题部分
  141. let title = document.getElementById("title");//需要拖拽
  142. /*添加需求:点击页面空白区域让登录窗消失 */
  143. window.onclick = function () {
  144. login.style.display = "none";
  145. bg.style.display = "none";
  146. }
  147. //a标签点击事件
  148. open.onclick = function (e) {
  149. login.style.display = "block";
  150. bg.style.display = "block";
  151. //阻止事件冒泡
  152. e.stopPropagation();
  153. }
  154. //关闭按钮点击事件
  155. document.getElementById("closeBtn").onclick = function () {
  156. login.style.display = "none";
  157. bg.style.display = "none";
  158. };
  159. //title按下事件
  160. title.onmousedown = function (e) {
  161. e = e || window.event;
  162. let x = getPagePoint(e).pageX - login.offsetLeft;
  163. let y = getPagePoint(e).pageY - login.offsetTop;
  164. //页面添加鼠标移动事件
  165. document.onmousemove = function (event) {
  166. event = event || window.event;
  167. //login大盒子的margin-left: -256px, margin-top: 140px
  168. //1 - -256 = 257 减去负数就相当于加这个数 (负负得正)
  169. login.style.left = getPagePoint(event).pageX - x + 256 + "px";
  170. login.style.top = getPagePoint(event).pageY - y - 140 + "px";
  171. }
  172. //鼠标弹起后停止移动事件
  173. this.onmouseup = function () {
  174. document.onmousemove = null;
  175. }
  176. }
  177. </script>
  178. </body>
  179. </html>

1.4-阻止事件冒泡

本小节知识点:阻止事件冒泡

  • 阻止事件冒泡:让同名事件不要在父元素中冒泡(触发)
    1. * 说人话:点击一个元素只会触发当前元素的事件,不会触发父元素的同名事件
  • 语法: 事件对象.stopPropagation() IE8及之前不支持

  • 事件对象.cancelBubble = true IE8之前支持

  • 注意:如果想要阻止事件冒泡,一定要在触发事件的函数中接收事件对象

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. #box{
  8. width: 300px;
  9. height: 300px;
  10. background-color: hotpink;
  11. position: relative;
  12. }
  13. #son{
  14. width: 100px;
  15. height: 100px;
  16. position: absolute;
  17. left: 350px;
  18. top: 350px;
  19. background-color: yellowgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div id="box">
  25. <input type="button" value="点我" id="btn"/>
  26. <div id="son"></div>
  27. </div>
  28. </body>
  29. </html>
  30. <script>
  31. /*本小节知识点:阻止事件冒泡
  32. * 阻止事件冒泡:让同名事件不要在父元素中冒泡(触发)
  33. * 说人话:点击一个元素只会触发当前元素的事件,不会触发父元素的同名事件
  34. * 语法: 事件对象.stopPropagation() IE8及之前不支持
  35. * 事件对象.cancelBubble = true IE8之前支持
  36. *
  37. * 注意:如果想要阻止事件冒泡,一定要在触发事件的函数中接收事件对象
  38. */
  39. window.onclick = function () {
  40. alert("window被点击了");
  41. }
  42. document.onclick = function () {
  43. alert("文档被点击了");
  44. }
  45. document.documentElement.onclick = function () {
  46. alert("html被点击了");
  47. }
  48. document.body.onclick = function () {
  49. alert("body被点击了");
  50. }
  51. document.getElementById("box").onclick = function (e) {
  52. e = e || window.event;
  53. alert("我是骚粉的大盒子");
  54. // e.stopPropagation();
  55. //e.cancelBubble = true;//IE8及之前
  56. stopPropagation(e);//兼容性封装函数
  57. //阻止事件冒泡的这行代码可以写在这个事件函数的任意位置,一般习惯写在最后面
  58. };
  59. document.getElementById("btn").onclick = function () {
  60. alert("我是小按钮");
  61. };
  62. document.getElementById("son").onclick = function () {
  63. alert("我是又黄又绿的小盒子");
  64. };
  65. /** 阻止事件冒泡兼容性封装
  66. * @param e:事件对象
  67. * @return 无
  68. */
  69. function stopPropagation( e) {
  70. e = e || window.event;
  71. if(e.stopPropagation){
  72. e.stopPropagation();
  73. }else{
  74. e.cancelBubble = true;
  75. }
  76. }
  77. </script>

05-事件捕获

1.1-事件捕获介绍

本小节知识点:事件捕获

  • 1.事件冒泡:从触发事件元素,一级一级往上找父元素触发同名事件,如果有就触发
  • 2.事件捕获:从最顶级的父元素一级一级往下找子元素触发同名事件,直到触发事件的元素为止

    • 事件捕获与事件冒泡触发事件的顺序完全相反
  • 3.事件捕获,只能通过addEventListener并且参数写true才是事件捕获

    • 其他都是冒泡(不是通过addEventListener添加、addEventListener参数为false)
  • 4.事件对象.stopPropagation() 除了可以阻止冒泡还可以阻止捕获
  • 5.IE8及以前没有捕获!
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. #box {
  8. width: 300px;
  9. height: 300px;
  10. background-color: hotpink;
  11. position: relative;
  12. }
  13. #son {
  14. width: 100px;
  15. height: 100px;
  16. position: absolute;
  17. left: 350px;
  18. top: 350px;
  19. background-color: yellowgreen;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div id="box">
  25. <div id="son"></div>
  26. </div>
  27. </body>
  28. </html>
  29. <script>
  30. /*本小节知识点:事件捕获
  31. 1.事件冒泡:从触发事件元素,一级一级往上找父元素触发同名事件,如果有就触发
  32. 2.事件捕获:从最顶级的父元素一级一级往下找子元素触发同名事件,直到触发事件的元素为止
  33. * 事件捕获与事件冒泡触发事件的顺序完全相反
  34. 3.事件捕获,只能通过addEventListener并且参数写true才是事件捕获
  35. * 其他都是冒泡(不是通过addEventListener添加、addEventListener参数为false)
  36. 4.事件对象.stopPropagation() 除了可以阻止冒泡还可以阻止捕获
  37. 5.IE8及以前没有捕获!
  38. */
  39. let box = document.getElementById("box");
  40. let son = document.getElementById("son");
  41. window.addEventListener("click", function () {
  42. alert("这是window");
  43. },true)
  44. document.addEventListener("click", function () {
  45. alert("这是document");
  46. },true)
  47. document.documentElement.addEventListener("click", function (e) {
  48. e = e || window.event;
  49. alert("这是html");
  50. e.stopPropagation();//阻止事件冒泡和事件捕获
  51. },true)
  52. document.body.addEventListener("click", function () {
  53. alert("这是body");
  54. },true)
  55. //参数3:默认是false,代表是支持事件冒泡
  56. box.addEventListener("click", function () {
  57. alert("这是box");
  58. },true)
  59. son.addEventListener("click", function () {
  60. alert("这是son");
  61. },true)
  62. </script>

1.2-事件三个阶段

本小节知识点:介绍事件的三个阶段

  • 1.事件一共有三个阶段:事件的执行顺序

    • 1—捕获阶段 :
    • 2—目标阶段 :
    • 3—冒泡阶段 :
  • 2.事件对象.eventPhase 可以获得触发这个事件时,到底是哪个阶段
  • 3.先从最顶级往下一级一级捕获,然后到目标的捕获,目标的冒泡,再一级一级往上冒泡
  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title>标题</title>
  6. <style>
  7. .one {
  8. width: 200px;
  9. height: 200px;
  10. background-color: pink;
  11. }
  12. .son {
  13. width: 100px;
  14. height: 100px;
  15. background-color: green;
  16. position: absolute;
  17. left: 250px;
  18. top: 250px;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <div class="one" id="box">
  24. <input type="button" value="按钮" id="btn"/>
  25. <div class="son" id="son"></div>
  26. </div>
  27. <script>
  28. /*本小节知识点:介绍事件的三个阶段
  29. 1.事件一共有三个阶段:事件的执行顺序
  30. 1--捕获阶段 :
  31. 2--目标阶段 :
  32. 3--冒泡阶段 :
  33. 2.事件对象.eventPhase 可以获得触发这个事件时,到底是哪个阶段
  34. 3.先从最顶级往下一级一级捕获,然后到目标的捕获,目标的冒泡,再一级一级往上冒泡
  35. */
  36. let box = document.getElementById("box");
  37. let btn = document.getElementById("btn");
  38. let son = document.getElementById("son");
  39. document.addEventListener("click",function (e) {
  40. alert("document"+ e.eventPhase);
  41. },true) ;//true表示事件捕获,所以是阶段1,并且优先执行
  42. document.body.addEventListener("click", function (e) {
  43. alert("哈哈,我是body"+ e.eventPhase);
  44. },false);
  45. box.addEventListener("click",function (e) {
  46. alert("哈哈哈,我是粉色的盒子box..."+ e.eventPhase);
  47. },false);
  48. btn.addEventListener("click",function (e) {
  49. alert("哈哈哈,我是按钮btn..."+ e.eventPhase);
  50. },false);
  51. son.addEventListener("click",function (e) {
  52. alert("嘻嘻嘻,我是绿色的盒子son"+ e.eventPhase);
  53. },false);
  54. </script>
  55. </body>
  56. </html>

06-事件对象补充属性(事件类型、键盘按键)

1.1-事件类型e.type

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <!--
  7. 事件对象.type 能获取到触发事件的事件名
  8. -->
  9. </head>
  10. <body>
  11. <input type="button" value="按钮" id="btn"/>
  12. </body>
  13. </html>
  14. <script>
  15. let btn = document.getElementById('btn');
  16. /*
  17. btn.onclick = function (e) {
  18. console.log("我被点了");
  19. console.log(e.type);//获取事件名,获取到的是click
  20. };
  21. btn.onmouseover = function (e) {
  22. console.log(e.type);//mouseover
  23. };
  24. */
  25. btn.onclick = f1;
  26. btn.onmouseover = f1;
  27. function f1(e){
  28. //如果是点击触发的,那么就是click,如果是鼠标移入触发的就是mouseover
  29. console.log(e.type);
  30. }
  31. </script>

1.2-键盘事件及获取键盘按键

本小节知识点:介绍键盘的事件和获取按键

  • 1.键盘事件

    • onkeydown:键盘按下触发
    • onkeyup:键盘弹起触发
    • onkeypress:键盘按下并弹起会触发
    • onkeydown和onkeypress的区别:了解即可

      • onkeypress可以过滤掉特殊的功能键例如删除、F1-F12,shift,alt键等等,onkeydown不会过滤
      • onkeypress可以区分大小写,但是onkeydown永远都是大写(不管大小写状态)
  • 2.如何获取你到底按的是哪个键?

    • 通过事件对象获取 语法: 事件对象.keyCode
    • 获取到的是键盘对应字符的ascii码
    • ascii码转字符:String.fromCharCode(code)
  • 3.有三个属性都可以获取到按下的键

    • keyCode(IE8及之前),charCode,which

    • 所以为了保证一定能获取到,就做兼容
      let code = e.keyCode || e.charCode || e.which;

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. </body>
  9. </html>
  10. <script>
  11. /*本小节知识点:介绍键盘的事件和获取按键
  12. 1.键盘事件
  13. onkeydown:键盘按下触发
  14. onkeyup:键盘弹起触发
  15. onkeypress:键盘按下并弹起会触发(用的比较多)
  16. onkeydown和onkeypress的区别:了解即可
  17. 1.onkeypress可以过滤掉特殊的功能键例如删除、F1-F12,shift,alt键等等,onkeydown不会过滤
  18. 2.onkeypress可以区分大小写,但是onkeydown永远都是大写(不管大小写状态)
  19. 2. 如何获取你到底按的是哪个键?
  20. * 通过事件对象获取 语法: 事件对象.keyCode
  21. * 获取到的是键盘对应字符的ascii码
  22. * ascii码转字符:String.fromCharCode(code)
  23. 3.有三个属性都可以获取到按下的键
  24. keyCode(IE8及之前),charCode,which
  25. keydown\keyup:keyCode
  26. keypress:charCode
  27. 所以为了保证一定能获取到,就做兼容
  28. let code = e.keyCode || e.charCode || e.which;
  29. */
  30. document.onkeypress = function (e) {
  31. e = e || window.event
  32. let code = e.keyCode || e.charCode || e.which;
  33. console.log("press触发了 : " + code);
  34. //根据ASCII码转换成字符
  35. console.log(String.fromCharCode(code));
  36. };
  37. //打开浏览器,按下任何键就触发了
  38. document.onkeydown = function (e) {
  39. e = e || window.event
  40. console.log("down触发了 : " + e.keyCode);
  41. console.log(String.fromCharCode(e.keyCode));
  42. };
  43. </script>

1.3-右键事件

  • 网页默认都有右键事件,是一个菜单

  • 右键事件:contextmenu

  • 阻止右键默认的事件:e.preventDefault()

  • 自定义右键菜单

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. * {
  8. padding: 0;
  9. margin: 0;
  10. }
  11. .box {
  12. display: none;
  13. position: fixed;
  14. width: 120px;
  15. border: 1px solid #dadce0;
  16. }
  17. .box li {
  18. list-style: none;
  19. width: 110px;
  20. float: left;
  21. line-height: 30px;
  22. padding-left: 10px;
  23. font-size: 14px;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <div class="box">
  29. <ul>
  30. <li>复制</li>
  31. <li>粘贴</li>
  32. <li>剪切</li>
  33. </ul>
  34. </div>
  35. <script>
  36. // 右键一般是默认事件,但是有些情况下不需要右键的默认事件,需要自定义,如游戏、办公系统等
  37. document.addEventListener('contextmenu',function(e){
  38. // 事件兼容处理
  39. e = e || window.event;
  40. // 阻止默认事件
  41. e.preventDefault();
  42. // 显示菜单:事件右侧
  43. let box = document.querySelector('.box');
  44. box.style.backgroundColor = '#ffffff';
  45. box.style.left = e.pageX + 'px';
  46. box.style.top = e.pageY + 'px';
  47. box.style.display = 'block';
  48. });
  49. </script>
  50. </body>
  51. </html>