1.事件

网页中的每个元素都可以产生某些事件。 比如:当用户单击按钮时,就发生一个鼠标单击(onclick)事件。 当用户点击提交按钮时,就发生一个提交数据(onsubmit)事件。 事件是可以被侦测到的行为。 每个元素都可以产生某些可以触发JavaScript函数的事件。
javaScript中的常用事件:
05.DOM编程 - 图1

1.1.javaScript中绑定事件方式

在javaScript中,给DOM元素绑定事件有三种方式:侵入式、绑定式、监听函数式。

  1. 侵入式事件方式:将javaScript事件直接写在html标签中

    1. <div onclick="add()">点我</div>
    2. <script>
    3. //事件处理函数
    4. function add(){
    5. console.log('点击了div对象');
    6. }
    7. </script>

    注意:此种方式的缺点是:javaScript事件与HTML代码混杂在一起。

  2. 绑定式事件方式:通过DOM对象,使用javaScript代码绑定一个事件

    1. <div>点我</div>
    2. <script>
    3. let divObj = document.getElementsByTagName('div')[0];
    4. //function()匿名函数就是事件处理函数
    5. divObj.onclick = function(){
    6. console.log('点击了div对象');
    7. }
    8. </script>

    注意:此种方式的优点是:

    1. 行间和事件分离。
    2. 可以给元素动态添加事件。
  3. 监听函数式事件方式:

    1. <div>点我</div>
    2. <script>
    3. let divObj = document.getElementsByTagName('div')[0];
    4. divObj.addEventListener('click',function(){
    5. console.log('点击了div对象');
    6. },false);
    7. </script>

    注意:addEventListener函数的三个参数:

    1. 事件名(没有前缀on)。
    2. 事件处理函数。
    3. 布尔类型(一般为false)。true:进行事件捕获; false:不进行事件捕获;

1.2.事件对象-event

event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
05.DOM编程 - 图2

1.2.1.鼠标坐标的使用

  1. <head>
  2. <meta charset="utf-8">
  3. <title></title>
  4. <style>
  5. div{
  6. width: 200px;
  7. height: 200px;
  8. background-color: blue;
  9. margin: 100px;
  10. }
  11. </style>
  12. </head>
  13. <body>
  14. <div><div>
  15. <script>
  16. document.getElementsByTagName('div')[0].onmousemove = function(event){
  17. console.log('相对视口坐标:'+event.clientX+','+event.clientY);
  18. console.log('相对触发事件对象坐标:'+event.offsetX+','+event.offsetY);
  19. }
  20. </script>
  21. </body>

1.2.2.keyCode的使用

  1. //获取键盘按键的keyCode
  2. document.onkeydown = function(event){
  3. console.log(event.keyCode);
  4. }

常用按键的keyCode值:回车13, 空格32,上38,下40,左37,右39

1.3.事件冒泡与事件捕获

在页面上的一块可视区域中,其中可能会包括父元素可视区域与子元素可视区域。
此时,如果用户触发了子元素的某个事件,而父元素也具有相同的事件,那么事实上,我们并不能确定:用户到底是想触发子元素事件,还是想触发父元素事件。
解决这个问题的思路是:设计两种事件流:

  1. 当用户触发了子元素事件时,先触发子元素事件,再触发父元素事件。这就是事件冒泡。(默认)
  2. 当用户触发了子元素事件时,先触发父元素事件,再触发子元素事件。这就是事件捕获。

下面演示事件冒泡:

  1. <head>
  2. <style>
  3. div{
  4. width: 200px;
  5. height: 200px;
  6. background-color: red;
  7. }
  8. div p{
  9. width: 100px;
  10. height: 100px;
  11. background-color: blue;
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <div>
  17. <p></p>
  18. </div>
  19. <script>
  20. let divObj = document.getElementsByTagName('div')[0];
  21. let pObj = divObj.getElementsByTagName('p')[0];
  22. divObj.onclick = function(){
  23. alert('父元素的点击事件被触发');
  24. }
  25. pObj.onclick = function(){
  26. alert('子元素的点击事件被触发');
  27. }
  28. </script>
  29. </body>

阻止事件冒泡: event.cancelBubble = true;

  1. pObj.onclick = function(event){
  2. alert('子元素的点击事件被触发');
  3. event.cancelBubble = true;
  4. }

1.4.浏览器默认行为

默认行为:在某些事件中,浏览器内置了一些默认的功能。 如:单击鼠标右键会弹出菜单、提交按钮默认提交动作、按下字母键会输入一个字母等。 如果这些默认行为不能满足我们需要的功能,那么可以阻止默认行为,重写我们希望的行为。 阻止默认行为很简单,在事件处理函数中调用preventDefault方法即可。 阻止默认行为: event.preventDefault();
下面是一个自定义右键菜单案例:

  1. <ul>
  2. <li>右键菜单项1</li>
  3. <li>右键菜单项2</li>
  4. <li>右键菜单项3</li>
  5. </ul>
  6. <script>
  7. let ulObj = document.getElementsByTagName('ul')[0];
  8. ulObj.style.border = 'solid 1px #666';
  9. ulObj.style.width = '100px';
  10. ulObj.style.position = 'absolute';
  11. ulObj.style.display = 'none';
  12. document.oncontextmenu = function(event){
  13. ulObj.style.display = 'block';
  14. ulObj.style.left = event.clientX+'px';
  15. ulObj.style.top = event.clientY+'px';
  16. event.preventDefault();
  17. }
  18. ulObj.onclick = function(){
  19. this.style.display = 'none';
  20. }
  21. </script>

1.5.表单元素事件

1.5.1.表单元素常用事件

05.DOM编程 - 图3

1.5.2.表单验证

表单是Web应用中的一个重要组成部分,通过表单,可以让用户与服务器端进行交互。
通常的做法是:用户通过页面表单中的各种控件(文本框、单选按钮、下拉列表等等),填入数据,表单再将这些数据发送给服务器端,进行业务处理。
但是,用户在填入数据的过程中,很有可能会填入错误的数据。此时,就需要在页面上,对用户输入的数据进行合法性验证,以保证用户必须填入正确的数据,进而保证发送给服务器端的数据都是正确的。
常用的表单验证有:

  1. 非空验证
  2. 长度验证
  3. 数字验证
  4. 日期时间格式验证
  5. 邮箱地址验证
  6. 网址验证
  7. … …
    1. <h3>登陆</h3>
    2. <form>
    3. 用户名:<input type="text" id="userName"><br>
    4. 密码:<input type="password" id="password"><br>
    5. <input type="button" value="提交" onclick="checkForm()">
    6. </form>
    7. <script>
    8. function checkForm(){
    9. let userName = document.getElementById('userName');
    10. let password = document.getElementById('password');
    11. //用户名非空验证
    12. if(userName.value==''){
    13. alert('用户名不能为空!');
    14. return;
    15. }
    16. //密码非空验证
    17. if(password.value==''){
    18. alert('密码不能为空!');
    19. return;
    20. }
    21. //密码长度必须为六位
    22. if(password.value.length!=6){
    23. alert('密码长度必须为6位!');
    24. return;
    25. }
    26. //密码必须全部为数字
    27. if(isNaN(password.value)){
    28. alert('密码必须全部为数字!');
    29. return;
    30. }
    31. alert('提交');
    32. }
    33. </script>

    2.DOM编程实际案例

    2.1.时钟

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8" />
    5. <title>时钟</title>
    6. </head>
    7. <body>
    8. <p id="myclock" style="font-size:24px"></p>
    9. <button id="startBtn">开始</button>
    10. <button id="stopBtn">停止</button>
    11. <script>
    12. let myclock = document.getElementById("myclock");
    13. let startBtn = document.getElementById("startBtn");
    14. let stopBtn = document.getElementById("stopBtn");
    15. callback();
    16. let mytimer = setInterval(callback, 1000);
    17. function callback() {
    18. var mydate = new Date();
    19. myclock.innerHTML = mydate.getHours() +
    20. ":" + mydate.getMinutes() +
    21. ":" + mydate.getSeconds();
    22. }
    23. //启动按钮事件
    24. startBtn.onclick = function() {
    25. if (mytimer == null) {
    26. mytimer = setInterval(callback, 1000);
    27. }
    28. };
    29. //停止按钮事件
    30. stopBtn.onclick = function() {
    31. clearInterval(mytimer);
    32. mytimer = null;
    33. };
    34. </script>
    35. </body>
    36. </html>

    2.2.全选

    05.DOM编程 - 图4
    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>全选</title>
    6. </head>
    7. <body>
    8. 全选<input class="btn" type="checkbox">
    9. <ul>
    10. <li><input type="checkbox">杜比环绕,家庭影院必备,超真实享受</li>
    11. <li><input type="checkbox">NVDIA 99999GT 2G 1024bit极品显卡,不容错过</li>
    12. <li><input type="checkbox">精品热卖,高清晰,45寸LED电视</li>
    13. <li><input type="checkbox">Sony索尼家用最新款笔记本</li>
    14. <li><input type="checkbox">华为,荣耀3C,超低价,性价比奇高</li>
    15. </ul>
    16. <script>
    17. let btn = document.getElementsByClassName('btn')[0];
    18. let inputArr = document.getElementsByTagName('ul')[0].getElementsByTagName('input');
    19. btn.onclick = function() {
    20. let bool = btn.checked;
    21. for (let i = 0; i < inputArr.length; i++) {
    22. inputArr[i].checked = bool;
    23. }
    24. }
    25. </script>
    26. </body>
    27. </html>

    2.3.图片轮播

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>图片轮播</title>
    6. <style>
    7. #lunbo {
    8. width: 1226px;
    9. height: 460px;
    10. position: relative;
    11. margin: 0 auto;
    12. }
    13. #lunbo img {
    14. width: 1226px;
    15. height: 460px;
    16. position: absolute;
    17. left: 0;
    18. top: 0;
    19. display: none;
    20. }
    21. </style>
    22. </head>
    23. <body>
    24. <div id="lunbo">
    25. <img src="img/lunbo1.jpg">
    26. <img src="img/lunbo2.jpg">
    27. <img src="img/lunbo3.jpg">
    28. <img src="img/lunbo4.jpg">
    29. <img src="img/lunbo5.jpg">
    30. <img src="img/lunbo6.jpg">
    31. </div>
    32. <script>
    33. let imgArr = document.getElementById('lunbo').getElementsByTagName('img');
    34. //图片数量
    35. let imgNum = imgArr.length
    36. //用此索引来跟踪图片轮播顺序(第一张图片索引即为0)
    37. let index = 0;
    38. //初始化第一张图片
    39. imgArr[0].style.display = 'block';
    40. //每隔3秒轮播一张图片
    41. setInterval(function(){
    42. index++;
    43. //如果轮播到最后一张图片,那么索引就归零
    44. if (index > imgNum - 1) {
    45. index = 0;
    46. }
    47. //先隐藏所有图片
    48. for (let i=0;i<imgNum; i++) {
    49. imgArr[i].style.display = 'none';
    50. }
    51. //再显示当前图片
    52. imgArr[index].style.display = 'block';
    53. }, 3000);
    54. </script>
    55. </body>
    56. </html>

    2.4.图片轮播(过渡效果)

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>图片轮播(过度效果)</title>
    6. <style>
    7. #lunbo {
    8. width: 1226px;
    9. height: 460px;
    10. position: relative;
    11. margin: 0 auto;
    12. }
    13. #lunbo img {
    14. width: 1226px;
    15. height: 460px;
    16. position: absolute;
    17. left: 0;
    18. top: 0;
    19. opacity: 0;
    20. /*display: none;*/
    21. }
    22. </style>
    23. </head>
    24. <body>
    25. <div id="lunbo">
    26. <img src="img/lunbo1.jpg">
    27. <img src="img/lunbo2.jpg">
    28. <img src="img/lunbo3.jpg">
    29. <img src="img/lunbo4.jpg">
    30. <img src="img/lunbo5.jpg">
    31. <img src="img/lunbo6.jpg">
    32. </div>
    33. <script>
    34. let imgArr = document.getElementById('lunbo').getElementsByTagName('img');
    35. //图片数量
    36. let imgNum = imgArr.length;
    37. //当前图片索引
    38. let index = 0;
    39. //上一张图片索引
    40. let preIndex = index;
    41. //当前图片初始透明度
    42. let opacityValue = 0;
    43. //上一张图片初始透明度
    44. let preOpacityValue = 1;
    45. //初始化第一张图片
    46. imgArr[index].style.opacity = 1;
    47. setInterval(function() {
    48. //每次切换时,确定当前图片索引与上一张图片索引
    49. preIndex = index;
    50. index++;
    51. //判断是否进行下一轮轮播
    52. if (index > imgNum-1) {
    53. index = 0;
    54. }
    55. //上一张图片隐藏
    56. hideImg();
    57. //当前图片显示
    58. showImg();
    59. }, 3000);
    60. function showImg() {
    61. //设置当前显示图片透明度初始值
    62. opacityValue = 0;
    63. //淡入动画
    64. let time = setInterval(function() {
    65. opacityValue += 0.05;
    66. if (opacityValue >= 1) {
    67. opacityValue = 1;
    68. clearInterval(time);
    69. }
    70. imgArr[index].style.opacity = opacityValue;
    71. }, 40);
    72. }
    73. function hideImg() {
    74. //设置上一张隐藏图片透明度初始值
    75. preOpacityValue = 1;
    76. //淡出动画
    77. let time = setInterval(function() {
    78. preOpacityValue -= 0.05;
    79. if (preOpacityValue <= 0) {
    80. preOpacityValue = 0;
    81. clearInterval(time);
    82. }
    83. imgArr[preIndex].style.opacity = preOpacityValue;
    84. }, 40);
    85. }
    86. </script>
    87. </body>
    88. </html>

    2.5.放大镜

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>放大镜</title>
    6. <style>
    7. #fdj {
    8. position: relative;
    9. width: 450px;
    10. height: 450px;
    11. }
    12. #fdj img{
    13. width: 450px;
    14. height: 450px;
    15. }
    16. #fdj .mengban {
    17. position: absolute;
    18. display: none;
    19. width: 225px;
    20. height: 225px;
    21. background-color: yellow;
    22. opacity: 0.4;
    23. cursor: move;
    24. left: 0;
    25. top: 0;
    26. }
    27. #fdj .fdjBox {
    28. position: absolute;
    29. width: 450px;
    30. height: 450px;
    31. top: 0;
    32. left: 460px;
    33. display: none;
    34. }
    35. </style>
    36. </head>
    37. <body>
    38. <!--这里是大图片-->
    39. <div id="fdj">
    40. <img src="img/dazi.jpg">
    41. <div class="mengban"></div>
    42. <div class="fdjBox"></div>
    43. </div>
    44. <script>
    45. <!-- onload能保证图片也加载完毕 -->
    46. window.onload = function() {
    47. let fdj = document.getElementById('fdj');
    48. let mengban = fdj.getElementsByClassName('mengban')[0];
    49. let fdjBox = fdj.getElementsByClassName('fdjBox')[0];
    50. //图片尺寸
    51. let imgWidth = fdj.getElementsByTagName('img')[0].width;
    52. fdj.onmousemove = function(event) {
    53. //这里获取了蒙板的left和top(offsetLeft是fdj距离视口的位置)
    54. let left = event.clientX - this.offsetLeft - imgWidth / 2 / 2;
    55. let top = event.clientY - this.offsetTop - imgWidth / 2 / 2;
    56. //console.log(left + ',' + top);
    57. if (left < 0) {
    58. left = 0;
    59. }
    60. if (left > this.offsetWidth - imgWidth/2) {
    61. left = this.offsetWidth - imgWidth/2;
    62. }
    63. if (top < 0) {
    64. top = 0;
    65. }
    66. if (top > this.offsetHeight - imgWidth/2) {
    67. top = this.offsetHeight - imgWidth/2;
    68. }
    69. mengban.style.left = left + 'px';
    70. mengban.style.top = top + 'px';
    71. mengban.style.display = 'block';
    72. fdjBox.style.backgroundImage = 'url(img/dazi.jpg)';
    73. fdjBox.style.backgroundRepeat = 'no-repeat';
    74. fdjBox.style.backgroundPosition = -left * 2 + 'px' + ' ' + -top * 2 + 'px';
    75. fdjBox.style.display = 'block';
    76. }
    77. fdj.onmouseout = function() {
    78. mengban.style.display = 'none';
    79. fdjBox.style.display = 'none';
    80. }
    81. }
    82. </script>
    83. </body>
    84. </html>

    2.6.走马灯

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>走马灯</title>
    6. <style>
    7. #container {
    8. width: 750px;
    9. height: 198px;
    10. margin: 0 auto;
    11. display: flex;
    12. }
    13. #container > img{
    14. width: 55px;
    15. height: 198px;
    16. }
    17. #container div{
    18. position: relative;
    19. width: 640px;
    20. height: 198px;
    21. overflow: hidden;
    22. display: flex;
    23. }
    24. #container div ul {
    25. list-style: none;
    26. margin: 0;
    27. padding: 0;
    28. position: absolute;
    29. width: 640px;
    30. height: 198px;
    31. left: 0px;
    32. top: 0px;
    33. display: flex;
    34. }
    35. #container div ul li {
    36. width: 160px;
    37. height: 198px;
    38. }
    39. </style>
    40. </head>
    41. <body>
    42. <!--图片尺寸:160*198-->
    43. <div id="container">
    44. <img src="img/left.jpg">
    45. <div>
    46. <ul>
    47. <li><a href="#"><img src="img/zmd1.jpg"></a></li>
    48. <li><a href="#"><img src="img/zmd2.jpg"></a></li>
    49. <li><a href="#"><img src="img/zmd3.jpg"></a></li>
    50. <li><a href="#"><img src="img/zmd4.jpg"></a></li>
    51. </ul>
    52. </div>
    53. <img src="img/right.jpg">
    54. </div>
    55. <script>
    56. window.onload = function() {
    57. let container = document.getElementById('container');
    58. let scoll = container.getElementsByTagName("ul")[0];
    59. let imgArr = document.querySelectorAll('#container > img');
    60. let btnLeft = imgArr[0];
    61. let btnRight = imgArr[1];
    62. //滚动速度
    63. let speed = 5;
    64. //滚动方向(初始向右)
    65. let fangxiang = 1;
    66. //获取图片数量
    67. let imgNum = scoll.getElementsByTagName("img").length;
    68. //获取图片宽度
    69. let imgWidth = scoll.getElementsByTagName("img")[0].width;
    70. //获取滚动条宽度
    71. let scollWidth = imgNum * imgWidth;
    72. //给滚动条加一倍的内容
    73. scoll.style.width = scollWidth * 2 + "px";
    74. scoll.innerHTML += scoll.innerHTML;
    75. //滚动条初始位置
    76. scoll.style.left = "-" + scollWidth + "px";
    77. let myTimer = setInterval(gundong, 40);
    78. function gundong() {
    79. if (fangxiang == 1) {
    80. if (scoll.offsetLeft >= 0) {
    81. scoll.style.left = "-" + scollWidth + "px";
    82. }
    83. } else {
    84. if (scoll.offsetLeft <= scollWidth * -1) {
    85. scoll.style.left = 0 + "px";
    86. }
    87. }
    88. scoll.style.left = scoll.offsetLeft + (speed * fangxiang) + "px";
    89. }
    90. btnLeft.onmouseover = function() {
    91. fangxiang = -1;
    92. };
    93. btnRight.onmouseover = function() {
    94. fangxiang = 1;
    95. };
    96. scoll.onmouseover = function() {
    97. clearInterval(myTimer);
    98. }
    99. scoll.onmouseout = function() {
    100. myTimer = setInterval(gundong, 40);
    101. }
    102. }
    103. </script>
    104. </body>
    105. </html>