JavaScript addEventListener()

为什么要使用 addEventListener() ?

从之前学习可以知道,我们可以使用事件属性(如 onclick、onmouseover 等)来为某个元素添加一个事件。不过这种方式有一个很大的弊端,那就是:一个事件属性只能添加一个处理程序,后面添加的处理程序会覆盖前面的。先来看一个例子。

示例 1:为同一个事件属性添加多个处理程序

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <button id="btn">按钮</button>
    <script>
        const oBtn = document.getElementById("btn");

        oBtn.onclick = function() {
            alert("第 1 次");
        };
        
        oBtn.onclick = function() {
            alert("第 2 次");
        };
        
        oBtn.onclick = function() {
            alert("第 3 次");
        };
    </script>
</body>
</html>

运行之后,页面效果如下图 1 所示。当我们点击【按钮】之后,会弹出一个对话框,如下图 2 所示。

JavaScript使用 “事件属性” (1)

JavaScript使用 “事件属性” (2)

分析:

在这个例子中,我们一开始的目的是想给按钮添加 3 次 onclick 事件,但 JavaScript 最终只会执行最后一次 onclick。从上面也可以看出来了,使用事件属性这种方式是没办法为一个元素添加多个相同事件的。

小伙伴们可能会在心里问:“那又如何?我们一般也不会为同一个元素添加多个相同事件啊。” 没错,对于同一个元素来说,确实很少需要添加多个相同事件的。可是,有些情况下确实需要这么做才行。比如在点击【提交表单】按钮时,需要验证由用户输入的全部数据,然后再通过 AJAX 将其提交给服务器。

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

JavaScript addEventListener() 语法

在 JavaScript 中,addEventListener() 方法解决了上面的问题,它具有以下主要优势:

  • 允许为同一个事件附加多个处理程序:我们可以使用 addEventListener() 为一个元素的同一个事件(如点击事件)添加多个不同的处理函数,它们会按照添加的顺序依次执行,而不会存在相互覆盖问题。
  • 支持事件冒泡和事件捕获:addEventListener() 提供了第 3 个参数,可以让我们控制事件处理程序是在 “事件冒泡” 阶段触发,还是在 “事件捕获” 阶段触发。
  • 可以更方便地移除事件监听器:我们可以通过 removeEventListener() 方法,来很方便地移除之前添加的监听器。
  • 更好的代码分离:将 JavaScript 事件处理代码与 HTML 结构完全分离,提高代码的可维护性。

语法:

obj.addEventListener(event, handler, options);

说明:

obj 是一个 DOM 对象。addEventListener() 接收以下 3 个参数。

  • event(必选):是一个字符串,表示要监听的事件类型。比如点击事件是 "click",鼠标移入事件是 "mouseover"。注意,这个事件类型是不需要加上 “on” 前缀的。
  • handler(必选):是一个函数,当指定的事件发生时,该函数会被调用执行。这个函数通常接收一个 event 对象作为参数,包含事件的详细信息。
  • options ( 可选 ):是一个对象,用于配置事件监听器的行为。该对象可以包含以下属性:
    • capture: 该属性是一个布尔值,默认值为 false。如果设置为 true,则表示在 “事件捕获“ 阶段触发处理程序;如果设置为 false 或省略,则表示在 “事件冒泡” 阶段触发处理程序。
    • once: 该属性是一个布尔值。如果设置为 true,则表示事件处理程序在触发一次后会自动移除。
    • passive: 该属性是一个布尔值。如果设置为 true,则表示事件处理程序不会调用 preventDefault()。一般常用于提高滚动性能。

提示: addEventListener() 是一个方法,它是 DOM 对象的一个方法。

JavaScript addEventListener() 示例

接下来,我们通过几个简单的例子来讲解 JavaScript addEventListener() 是如何使用的。

示例 2:addEventListener() 为一个按钮添加点击事件监听器

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <button id="btn">欢迎</button>
    <script>
        const oBtn = document.getElementById("btn");
        
        oBtn.addEventListener("click", function() {
            alert("欢迎来到绿叶网!");
        });
    </script>
</body>
</html>

运行之后,页面效果如下图 1 所示。当点击【欢迎】按钮之后,会弹出一个对话框,如下图 2 所示。

JavaScript 为一个按钮添加点击事件监听器(1)

JavaScript 为一个按钮添加点击事件监听器(2)

分析:

对于 addEventListener() 中的事件处理函数,如果内部逻辑代码比较多时,我们也可以单独拿出来放在别处定义。下面 2 种方式是等价的,小伙伴们可以试一下。

// 方式 1
oBtn.addEventListener("click", function() {
    alert("欢迎来到绿叶网!");
});

// 方式 2
function welcome() {
    alert("欢迎来到绿叶网!");
}
oBtn.addEventListener("click", welcome);

示例 3:addEventListener() 为一个元素添加多个相同事件的监听器

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <button id="btn">欢迎</button>
    <script>
        const oBtn = document.getElementById("btn");

        oBtn.addEventListener("click", function() {
            alert("第 1 次");
        });

        oBtn.addEventListener("click", function() {
            alert("第 2 次");
        });

        oBtn.addEventListener("click", function() {
            alert("第 3 次");
        });
    </script>
</body>
</html>

运行之后,页面效果如下图所示。当点击【欢迎】按钮之后,会连续弹出 3 次不同的对话框。

JavaScript 为一个元素添加多个相同事件的监听器

分析:

通过使用 addEventListener(),我们可以为同一个按钮的 “click” 事件添加了 3 个独立的事件处理程序,它们都会在点击按钮时依次执行。

示例 4:事件冒泡

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <div id="outer">
        外部 div
        <div id="inner">
            内部 div
        </div>
    </div>
    <script>
        const oOuter = document.getElementById("outer");
        const oInner = document.getElementById("inner");

        // 为外部 div 添加 click 事件
        oOuter.addEventListener("click", function() {
            alert("外部 div 被点击了!");
        });

        // 为内部 div 添加 click 事件
        oInner.addEventListener("click", function() {
            alert("内部 div 被点击了!");
        });
    </script>
</body>
</html>

页面效果如下图所示。

JavaScript addEventListener() 事件冒泡(1)

分析:

当我们点击 “内部 div” 时,会依次弹出两个对话框,如下图 1 和图 2 所示。

JavaScript addEventListener() 事件冒泡(2)

JavaScript addEventListener() 事件冒泡(3)

首先我们要清楚一件事,外部 div 是包裹着内部 div 的。因此当我们点击 “内部 div” 时,其实也相当于点击了 “外部 div”(因为内部 div 属于外部 div 的一部分)。然后再默认情况下,页面会采用事件冒泡的方式来触发。因此,内部 div 的 click 会被先触发,然后外部 div 的 click 后触发。

如果我们为外部 div 的 addEventListener() 添加 { capture: true } 选项,也就是改为下面代码:

oOuter.addEventListener("click", function() {
    alert("外部 div 被点了");
}, { capture: true });

然后再次点击 “内部 div”,然后会发现弹出对话框的顺序变了。其中,顺序如下图 1 和图 2 所示。

JavaScript addEventListener() 事件捕获(1)

JavaScript addEventListener() 事件捕获(2)

事件冒泡与事件捕获

事件冒泡 (Bubbling):就像水底的气泡往上冒一样,事件默认是从最具体的元素(内部 div)向上传递到最不具体的元素(外部 div)。

事件捕获 (Capturing):正好相反,事件从最外层(外部 div)向下传递到最具体的元素(内部 div),就像老鹰从天而降捕捉猎物一样。

addEventListener 默认使用冒泡模式,只有设置了 { capture: true } 才会开启捕获模式。

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号