Skip to content

事件进阶

事件监听器

在 JavaScript 中,如果要给元素添加一个事件,可采用以下两种方式:

  • 事件处理器
  • 事件监听器

如果我们要给元素添加一个事件,一般会通过操作 HTML 属性的方式来实现,这种方式其实也叫作“事件处理器”。

缺点:事件处理器不能为一个元素添加多个相同事件。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oBtn = document.getElementById("btn");
        oBtn.onclick = function () {
          alert("第 1 次");
        };
        oBtn.onclick = function () {
          alert("第 2 次");
        };
        oBtn.onclick = function () {
          alert("第 3 次");
        };
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="按钮" />
  </body>
</html>

在这个例子中,我们一开始的目的是给按钮添加 3 次 onclick 事件,但 JavaScript 最终只会执行最后一次 onclick。可以看出,事件处理器不能为一个元素添加多个相同事件。

疑问

第一次、第二次未执行,只执行了最后一次?还是第一次、第二次也已执行,但被第三次的执行结果所覆盖?

如果要为一个元素添加多个相同的事件,该如何实现呢?这就需要用到另外一种添加事件的方式了,那就是——事件监听器。

1.绑定事件

所谓的“事件监听器”,指的是使用 addEventListener() 方法为一个元素添加事件,我们又称之为“绑定事件”。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oBtn = document.getElementById("btn");
        oBtn.addEventListener(
          "click",
          function () {
            alert("第 1 次");
          },
          false
        );
        oBtn.addEventListener(
          "click",
          function () {
            alert("第 2 次");
          },
          false
        );
        oBtn.addEventListener(
          "click",
          function () {
            alert("第 3 次");
          },
          false
        );
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="按钮" />
  </body>
</html>

当我们点击按钮后,浏览器会 依次 弹出 3 个对话框。也就是说,我们可以使用“事件监听器”这种方式来为同一个元素添加多个相同的事件,而这一点是事件处理器做不到的。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      // 第 1 次调用 window.onload
      window.onload = function () {
        var oBtn1 = document.getElementById("btn1");
        oBtn1.onclick = function () {
          alert("第 1 次");
        };
      };
      // 第 2 次调用 window.onload
      window.onload = function () {
        var oBtn2 = document.getElementById("btn2");
        oBtn2.onclick = function () {
          alert("第 2 次");(
        };
      };
      // 第 3 次调用 window.onload
      window.onload = function () {
        var oBtn3 = document.getElementById("btn3");
        oBtn3.onclick = function () {
          alert("第 3 次");
        };
      };
    </script>
  </head>

  <body>
    <input id="btn1" type="button" value="按钮 1" /><br />
    <input id="btn2" type="button" value="按钮 2" /><br />
    <input id="btn3" type="button" value="按钮 3" />
  </body>
</html>

在实际开发中,我们有可能会多次使用 window.onload,但是会发现 JavaScript 只执行最后一次 window.onload。为了解决这个问题,我们可以使用 addEventListener() 来实现。在这个例子中,我们只需要将每一个 window.onload 改为以下代码即可。

html
window.addEventListener("load", function () {……}, false);
  • 事件监听器,可以为同一个元素添加多个相同的事件
    • obj.addEventListener(type, fn, false)
    • type 是个 string,事件类型,比如 click,不需要加 on
    • fn 是个函数名,或者是个匿名函数
    • false 表示事件冒泡阶段调用
    • ogj.removeEventListener(type, fn, false),解绑,fn 一定需要是函数名,不能是匿名函数
  • 在实际开发中,我们有可能会多次使用 window.onload,但是会发现 JavaScript 只执行最后一次 window.onload。为了解决这个问题,我们可以使用 addEventListener() 来实现
    • window.addEventListener("load", fn, false);
    • 或者用自定义的 addLoadEvent() 函数

event 对象

当一个事件发生的时候,这个事件有关的详细信息都会临时保存到一个指定的地方,这个地方就是 event 对象。

在 JavaScript 中,我们可以通过 event 对象来获取一个事件的详细信息。

属性说明
type事件类型
keyCode键码值
shiftKey是否按下 Shift
ctrlKey是否按下 Ctrl
altKey是否按下 Alt
  • 在 JavaScript 中,我们可以使用 event.type 来获取事件的类型
html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oBtn = document.getElementById("btn");
        oBtn.onclick = function (e) {
          alert(e.type);
        };
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="按钮" />
  </body>
</html>

DANGER

想当然地以为,当鼠标点击按钮时,跳出的菜单文字会出现 button,结果出现的却是 click 。

  • 在 JavaScript 中,如果我们想要获取键盘中的键对应的键码,可以使用 event.keyCode
  • 如果是 Shift 键、Ctrl 键和 Alt 键,我们不需要通过 keyCode 属性来获取,而可以通过 shiftKey、ctrlKey 和 altKey 属性来获取

this

在事件操作中,可以这样理解:哪个 DOM 对象(元素节点)调用了 this 所在的函数,那么 this 指向的就是哪个 DOM 对象。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oDiv = document.getElementsByTagName("div")[0];
        oDiv.onclick = function () {
          this.style.color = "hotpink";
        };
      };
    </script>
  </head>

  <body>
    <div>马拉松派,我们都在努力地成为长期主义者!</div>
  </body>
</html>

那么,为什么用 oLi[i] 不正确,而必须要用 this 呢?其实这就是典型的闭包问题。对于闭包,我们在 JavaScript 进阶中再详细介绍。在事件函数中,如果想要使用当前的元素节点,我们应该尽量使用 this 来代替 oBtn、oLi[i] 等写法。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oUl = document.getElementById("list");
        var oLi = oUl.getElementsByTagName("li");
        for (var i = 0; i < oLi.length; i++) {
          oLi[i].onclick = function () {
            // oLi[i].style.color = "hotpink";
            this.style.color = "hotpink";
          };
        }
      };
    </script>
  </head>

  <body>
    <ul id="list">
      <li>HTML</li>
      <li>CSS</li>
      <li>JavaScript</li>
    </ul>
  </body>
</html>
最近更新