事件

一、键盘事件

  • 键盘事件可以给表单元素绑定,该事件是针对当前表单元素,光标在input框里的时候,才会触发该事件
  • 如果給window、body绑定键盘事件,则在哪里敲击键盘都会触发该事件
  • div、p、….等,不能绑定该事件
  • 表单元素才有value属性
  1. /*
  2. + 键盘事件可以给表单元素绑定,该事件是针对当前表单元素,光标在input框里的时候,才会触发该事件
  3. + 如果給window、body绑定键盘事件,则在哪里敲击键盘都会触发这件
  4. + div、p、....等,不能绑定该事件
  5. */
  6. // 表单元素才有value属性
  7. let inp = document.getElementById("inp");
  8. inp.onkeydown = function () {
  9. // this.value 获取的是上一次input框里的值
  10. console.log("键盘按下", this.value);
  11. }
  12. // onkeypress 是键盘按下状态的事件
  13. inp.onkeypress = function () {
  14. // this.value 获取的是上一次input框里的值
  15. console.log("键盘", this.value);
  16. }
  17. inp.onkeyup = function () {
  18. // this.value 获取的是目前输入input框里的最新的值,因为数执行的时候,内容已经输入了。
  19. console.log("键盘抬起", this.value);
  20. }

二、事件对象

1、keyCode 码

  1. // keyCode 键盘上每个按键的键码值
  2. document.body.onkeyup = function (ev) {
  3. console.log(ev);
  4. console.log("当前按键的keyCode码: " + ev.keyCode);
  5. }

推箱子案例

  1. <head>
  2. <meta charset="UTF-8">
  3. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  4. <title>Document</title>
  5. <style>
  6. * {
  7. margin: 0;
  8. padding: 0;
  9. }
  10. .box {
  11. width: 200px;
  12. height: 200px;
  13. background-color: green;
  14. border-radius: 10px;
  15. position: absolute;
  16. left: 0;
  17. right: 0;
  18. top: 0;
  19. bottom: 0;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="box">
  25. </div>
  26. <script>
  27. let box = document.querySelector(".box"),
  28. keycode,
  29. css = getComputedStyle(box);
  30. let left = parseFloat(css.left);
  31. let top1 = parseFloat(css.top);
  32. let right = parseFloat(css.right);
  33. let bottom = parseFloat(css.bottom);
  34. document.body.onkeydown = function (ev) {
  35. let winH = document.documentElement.clientHeight;
  36. let winW = document.documentElement.clientWidth;
  37. let boxH = box.offsetHeight;
  38. let boxW = box.offsetWidth;
  39. let boxT = box.offsetTop;
  40. let boxL = box.offsetLeft;
  41. keycode = ev.keyCode;
  42. switch (keycode) {
  43. case 37:
  44. if (boxL > 0) {
  45. left -= 10;
  46. }
  47. break;
  48. case 38:
  49. if (boxT > 0) {
  50. top1 -= 10;
  51. }
  52. break;
  53. case 39:
  54. if (winW - boxW - boxL > 0) {
  55. left += 10;
  56. }
  57. break;
  58. case 40:
  59. if (winH - boxH - boxT > 0) {
  60. top1 += 10;
  61. }
  62. break;
  63. }
  64. box.style.left = left + "px";
  65. box.style.top = top1 + "px";
  66. }
  67. </script>
  68. </body>

2、坐标属性

  1. /*
  2. * 相对于当前浏览器的可视窗口的位置:clientX、clientY
  3. * 相对于当前盒子的位置:offsetX、offsetY
  4. * 相对于当前的body的位置:pageX、pageY
  5. * target:目标源,当前点击的是哪个元素元素,target就是谁
  6. * type:事件类型
  7. * 阻止事件的默认行为
  8. * e.cancelBubble:阻止事件的默认冒泡传播 (e.cancelBubble = true // 有兼容)
  9. * e.stopPropagation:阻止事件的默认冒泡传播(e.stopPropagation();)
  10. * e.preventDefault(); // 阻止事件的默认行为
  11. * e.returnValue = false// 阻止事件的默认行为 有兼容
  12. */
  13. // 1、无边框的盒子
  14. box.onclick = function (ev) {
  15. // ev事件
  16. console.log(ev);
  17. // 鼠标在盒子中点击时距离浏览器body的x坐标值
  18. console.log("距离浏览器左边框: " + ev.clientX);
  19. // 鼠标在盒子中点击时距离浏览器body的y坐标值
  20. console.log("距离浏览器上边框: " + ev.clientY);
  21. // 鼠标在盒子中点击时距离当前盒子最左侧的值(不包含边框)
  22. console.log("距离当前盒子左内边框: " + ev.offsetX);
  23. // 鼠标在盒子中点击时距离当前盒子最上侧的值(不包含边框)
  24. console.log("距离当前盒子上内边框: " + ev.offsetY);
  25. // 鼠标在盒子中点击时距离当前盒子最左侧的值
  26. console.log("距离body的左内边框: " + ev.pageX);
  27. // 鼠标在盒子中点击时距离当前盒子最上侧的值
  28. console.log("距离body的上内边框: " + ev.pageY);
  29. }
  30. // 2、有边框的盒子
  31. box2.onclick = function (ev) {
  32. // ev事件
  33. console.log(ev);
  34. // 鼠标在盒子中点击时距离浏览器body的x坐标值
  35. console.log("距离浏览器左边框: " + ev.clientX);
  36. // 鼠标在盒子中点击时距离浏览器body的y坐标值
  37. console.log("距离浏览器上边框: " + ev.clientY);
  38. // 鼠标在盒子中点击时距离当前盒子最左侧的值(不包含边框)
  39. console.log("距离当前盒子左内边框: " + ev.offsetX);
  40. // 鼠标在盒子中点击时距离当前盒子最上侧的值(不包含边框)
  41. console.log("距离当前盒子上内边框: " + ev.offsetY);
  42. }

自定义右击菜单栏案例

  1. <head>
  2. <meta charset="UTF-8">
  3. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  4. <title>自定义菜单栏</title>
  5. <style>
  6. * {
  7. margin: 0;
  8. padding: 0;
  9. }
  10. ul {
  11. list-style: none;
  12. }
  13. .box {
  14. width: 100px;
  15. background-color: red;
  16. border-radius: 8px;
  17. position: absolute;
  18. display: none;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <div class="box" id="box">
  24. <ul>
  25. <li>1</li>
  26. <li>2</li>
  27. <li>3</li>
  28. <li>4</li>
  29. </ul>
  30. </div>
  31. <script>
  32. window.oncontextmenu = function (ev) {
  33. let colors = ["red", "green", "orange", "lawngreen", "aliceblue", "aquamarine"];
  34. let num;
  35. let newArr = [];
  36. let lis = document.querySelectorAll(".box li");
  37. for (let i = 0; i < 4; i++) {
  38. num = Math.round(Math.random() * 4);
  39. if (newArr.includes(colors[num])) {
  40. i--;
  41. } else {
  42. newArr.push(colors[num]);
  43. }
  44. }
  45. // 1、关闭默认菜单栏
  46. ev.returnValue = false;
  47. // 2、自定义菜单栏显示
  48. box.style.display = "block";
  49. for (let i = 0; i < newArr.length; i++) {
  50. lis[i].style.background = newArr[i];
  51. }
  52. // 3、获取鼠标右击时的坐标
  53. let x = ev.clientX;
  54. let y = ev.clientY;
  55. console.log(x, y)
  56. // 4、x,y給盒子定位
  57. box.style.left = x + "px"; // 单位一定写!!!!
  58. box.style.top = y + "px";
  59. }
  60. </script>
  61. </body>

三、事件的传播机制

  • 所有的事件触发时,首先执行捕获阶段();
  • 其次进入目标阶段(找到目标的阶段,该阶段没有先捕获后冒泡,而是先绑定谁,就先执行谁);
  • 最后执行冒泡阶段。

1、事件的冒泡(由里向外冒泡)

  1. <head>
  2. <meta charset="UTF-8">
  3. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  4. <title>事件的默认传播机制</title>
  5. <style>
  6. div {
  7. width: 200px;
  8. height: 200px;
  9. background-color: sienna;
  10. border-radius: 8px;
  11. display: flex;
  12. justify-content: center;
  13. align-items: center;
  14. margin: 20px auto;
  15. }
  16. div.inner {
  17. width: 150px;
  18. height: 150px;
  19. background-color: red;
  20. border-radius: 8px;
  21. }
  22. div.center {
  23. width: 80px;
  24. height: 80px;
  25. background-color: lightcyan;
  26. border-radius: 8px;
  27. }
  28. </style>
  29. </head>
  30. <body>
  31. <div class="outer">
  32. <div class="inner">
  33. <div class="center"></div>
  34. </div>
  35. </div>
  36. <script>
  37. let outer = document.querySelector(".outer");
  38. let center = document.querySelector(".center");
  39. let inner = document.querySelector(".inner");
  40. // DOM1级绑定事件
  41. /* // 输出的ev.target 都是center的div
  42. outer.onclick = function (ev) {
  43. console.log("1outer");
  44. console.dir("触发源target: " + ev.target);
  45. }
  46. inner.onclick = function (ev) {
  47. console.log("2inner");
  48. console.dir("触发源target: " + ev.target);
  49. }
  50. center.onclick = function (ev) {
  51. console.log("3center");
  52. console.dir("触发源target: " + ev.target);
  53. } */
  54. // DOM2级绑定事件
  55. function fn1() {
  56. console.log("1outer");
  57. }
  58. function fn2() {
  59. console.log("2inner");
  60. }
  61. function fn3() {
  62. console.log("3center");
  63. }
  64. outer.addEventListener("click", fn1);
  65. center.addEventListener("click", fn3);
  66. inner.addEventListener("click", fn2);
  67. </script>
  68. </body>

2、事件的捕获机制(从外往里捕获)

  1. <body>
  2. <div class="outer">
  3. <div class="inner">
  4. <div class="center"></div>
  5. </div>
  6. </div>
  7. <script>
  8. let outer = document.querySelector(".outer");
  9. let center = document.querySelector(".center");
  10. let inner = document.querySelector(".inner");
  11. // DOM2级绑定事件
  12. function fn1() {
  13. console.log("outer 冒泡");
  14. }
  15. function fn2() {
  16. console.log("inner 冒泡");
  17. }
  18. function fn3() {
  19. console.log("center 冒泡");
  20. }
  21. function fn11() {
  22. console.log("outer 捕获");
  23. }
  24. function fn22() {
  25. console.log("inner 捕获");
  26. }
  27. function fn33() {
  28. console.log("center 捕获");
  29. }
  30. /*
  31. * addEventListener第三个参数(默认false)
  32. * false --- 冒泡
  33. * true --- 捕获
  34. */
  35. outer.addEventListener("click", fn1);
  36. outer.addEventListener("click", fn11, true);
  37. center.addEventListener("click", fn3);
  38. center.addEventListener("click", fn33, true);
  39. inner.addEventListener("click", fn2);
  40. inner.addEventListener("click", fn22, true);
  41. </script>
  42. </body>

四、事件的委托

  1. <head>
  2. <meta charset="UTF-8">
  3. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  4. <title>事件委托</title>
  5. </head>
  6. <body>
  7. <ul id="box">
  8. <li>1</li>
  9. <li>2</li>
  10. <li>3</li>
  11. <li>4</li>
  12. <li>5</li>
  13. </ul>
  14. <script>
  15. /* let list = document.querySelectorAll("#box li");
  16. for (let i = 0; i < list.length; i++) {
  17. list[i].onclick = function () {
  18. console.log(this.innerText);
  19. }
  20. } */
  21. // 利用事件委托 绑定点击事件,实现打印每一个点击元素的文本值
  22. let box = document.querySelector("#box");
  23. box.onclick = function (ev) {
  24. console.log(ev);
  25. console.log(ev.toElement.innerText);
  26. }
  27. </script>
  28. </body>

五、鼠标跟随案例

  1. <head>
  2. <meta charset="UTF-8">
  3. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  4. <title>鼠标跟随</title>
  5. <style>
  6. * {
  7. margin: 0;
  8. padding: 0;
  9. }
  10. .box {
  11. width: 200px;
  12. height: 200px;
  13. background-color: lightslategray;
  14. border-radius: 8px;
  15. position: relative;
  16. margin: 50px auto;
  17. }
  18. .mark {
  19. width: 50px;
  20. height: 50px;
  21. background-color: red;
  22. border-radius: 8px;
  23. position: absolute;
  24. cursor: move;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <div class="box" id="box">
  30. <!-- <div class="mark" id="mark">
  31. 光标
  32. </div> -->
  33. </div>
  34. <script>
  35. // 光标移入事件
  36. let mark;
  37. box.onmouseenter = function () {
  38. mark = document.createElement("div");
  39. mark.classList.add("mark");
  40. mark.id = "mark";
  41. box.appendChild(mark);
  42. }
  43. // 光标移动事件
  44. box.onmousemove = function (ev) {
  45. let curLeft = ev.clientX - box.offsetLeft - mark.offsetHeight / 2;
  46. let curTop = ev.clientY - box.offsetTop - mark.offsetWidth / 2;
  47. // console.log(ev.clientX, box.offsetLeft);
  48. // 判断盒子的坐标位置,不让其移出大盒子
  49. let maxLeft = box.offsetWidth - mark.offsetWidth;
  50. let maxTop = box.offsetHeight - mark.offsetHeight;
  51. if (curLeft <= 0) curLeft = 0;
  52. else if (curLeft >= maxLeft) curLeft = maxLeft;
  53. if (curTop <= 0) curTop = 0;
  54. else if (curTop > maxTop) curTop = maxTop;
  55. mark.style.left = curLeft + "px";
  56. mark.style.top = curTop + "px";
  57. }
  58. // 光标移出事件
  59. box.onmouseleave = function () {
  60. box.removeChild(mark);
  61. }
  62. </script>
  63. </body>