Skip to content

DOM EventListener

addEventListener() 方法是向 HTML 元素(或 window、document 等其他事件目标)附加事件处理程序的标准且最灵活的方式。

Section titled “addEventListener() 方法是向 HTML 元素(或 window、document 等其他事件目标)附加事件处理程序的标准且最灵活的方式。”
document.getElementById("myBtn").addEventListener("click", displayDate);

addEventListener() 的主要特点:

  • 将一个事件处理函数附加到元素上,而不会覆盖现有处理程序。
  • 允许为同一个元素添加多个相同事件类型或不同事件类型的处理程序。
  • 可用于支持事件的任何 DOM 对象(例如,元素、document、window)。
  • 提供了对事件传播阶段(event propagation phase,冒泡或捕获)的控制。
  • 促进了 JavaScript 逻辑与 HTML 标记的分离,从而得到更清晰、更易于维护的代码。
  • 可以使用 removeEventListener() 方法移除事件监听器(event listeners)。

element.addEventListener(event, function, optionsOrUseCapture);

参数如下:

  1. event:表示事件类型(例如,"click"、"mouseover"、"keydown")的字符串。注意:不要使用 “on” 前缀(使用 "click",而不是 "onclick")。
  2. function:当事件发生时将被调用的函数(事件处理程序)。此函数将接收一个 Event 对象作为其第一个参数。
  3. optionsOrUseCapture(可选):可以是一个布尔值或一个对象。

你可以使用匿名函数(anonymous function)或命名函数(named function)作为事件处理程序。

// Using an anonymous arrow function
const button = document.getElementById('myButton');
button.addEventListener("click", () => {
alert("Hello World!");
});
// Using a named function
const anotherButton = document.getElementById('anotherBtn');
function greetUser() {
alert("Greetings from named function!");
}
anotherButton.addEventListener("click", greetUser);

事件处理程序函数会自动接收一个 Event 对象(或更具体的类型,如 MouseEvent、KeyboardEvent)作为其第一个参数。此对象包含有关事件的信息,例如:

  • event.target:触发事件的元素。
  • event.currentTarget:附加事件监听器的元素。
  • event.preventDefault():取消浏览器默认事件行为的方法(如果可取消)。
  • event.stopPropagation():阻止事件进一步传播(冒泡或捕获)的方法。
button.addEventListener("click", (event) => {
console.log(`Event type: ${event.type}`);
console.log(`Target element: ${event.target.tagName}`);
// To prevent a form submission, for example:
// if (event.target.type === 'submit') event.preventDefault();
});

给同一元素添加多个事件处理程序

Section titled “给同一元素添加多个事件处理程序”

addEventListener() 允许你为同一个元素附加多个相同事件类型或不同事件类型的处理程序,它们不会互相覆盖。

const interactiveElement = document.getElementById('interactive');
function logClick() {
console.log('Clicked!');
}
function highlightElement() {
interactiveElement.style.backgroundColor = 'yellow';
}
interactiveElement.addEventListener("click", logClick);
interactiveElement.addEventListener("click", highlightElement); // Both will run on click
interactiveElement.addEventListener("mouseover", () => {
interactiveElement.style.border = '2px solid red';
});

你可以为全局对象(如 window 或 document)添加事件监听器,以便在全局级别处理页面加载、窗口大小调整或按键等事件。

window.addEventListener("resize", () => {
const newWidth = window.innerWidth;
document.getElementById("dimensionsDisplay").textContent = `Window width: ${newWidth}px`;
});
document.addEventListener('DOMContentLoaded', () => {
console.log('HTML fully loaded and parsed');
// Safe to manipulate the DOM here
});

如果你的事件处理程序函数需要参数,你不能像 myFunction(p1, p2) 那样直接在 addEventListener 中传递。相反,使用一个匿名函数或箭头函数(arrow function)来调用你的目标函数,并传递所需参数:

function greet(name, message) {
alert(`${message}, ${name}!`);
}
const greetButton = document.getElementById('greetBtn');
// Use an anonymous arrow function to call greet with parameters
greetButton.addEventListener("click", () => {
greet("Alice", "Welcome");
});

事件传播(Event propagation)是指当事件发生在嵌套元素上时,事件处理程序执行的顺序。事件传播主要有两个阶段:

  • 捕获阶段(Capturing Phase):事件从 window 对象向下传播到目标元素。注册了捕获阶段的监听器在此阶段触发。
  • 目标阶段(Target Phase):事件到达目标元素。
  • 冒泡阶段(Bubbling Phase):事件从目标元素向上(冒泡)传播回 window 对象。注册了冒泡阶段的监听器(默认)在此阶段触发。

如果你有一个 <p> 元素位于一个 <div> 元素内部,并且用户点击了 <p> 元素:

  • 在捕获阶段,<div> 的点击监听器(如果设置为捕获)将在 <p> 的点击监听器之前触发。
  • 在冒泡阶段(默认),<p> 的点击监听器将首先触发,然后是 <div> 的点击监听器。

你可以使用 addEventListener() 的第三个参数来指定阶段:

// To use capturing phase:
element.addEventListener("click", myFunction, true);
// Or using the options object:
element.addEventListener("click", myFunction, { capture: true });
// Default (bubbling phase):
element.addEventListener("click", myFunction, false);
element.addEventListener("click", myFunction); // Equivalent to false
element.addEventListener("click", myFunction, { capture: false }); // Explicitly bubbling

要移除使用 addEventListener() 附加的事件处理程序,必须使用 removeEventListener()。关键的是,你需要传递最初添加的完全相同的函数引用。这意味着匿名函数不能轻易移除,除非它们被赋值给了变量。

const myElement = document.getElementById('removableListenerElement');
function handleMouseMove(event) {
console.log(`Mouse at: X=${event.clientX}, Y=${event.clientY}`);
}
myElement.addEventListener("mousemove", handleMouseMove);
// To remove it later:
// myElement.removeEventListener("mousemove", handleMouseMove);

你还必须指定与添加监听器时相同的事件类型和 useCapture/options 值。

addEventListener() 和 removeEventListener() 是 DOM 的基本组成部分,并得到所有现代浏览器的完全支持。像 attachEvent(用于 Internet Explorer 8 及更早版本)这样的旧的非标准方法已经过时,不应在新的开发中使用。

有关所有 HTML DOM 事件和 Event 对象的详细信息,请查阅 MDN Web Docs 上的事件参考(Event reference)。