addEventListener

addEventListener 是 DOM 事件监听的核心 API,用于在指定目标上注册事件处理函数并配置捕获、一次性与 passive 等监听选项。

#tech / dev / frontend #platform / browser #type / concept #status / evergreen

[!info] related notes

addEventListener

addEventListener() 是 DOM 事件系统中最常用的监听注册方法。它让元素、documentwindow 等事件目标可以订阅某类事件,并在事件发生时执行处理函数。

一句话定义

addEventListener(type, listener, options) 用来给事件目标注册监听器,并决定它在什么阶段、以什么方式执行。

基本签名

target.addEventListener(type, listener)
target.addEventListener(type, listener, useCapture)
target.addEventListener(type, listener, options)

参数含义:

  • type:事件类型,例如 clickinputkeydown
  • listener:监听函数
  • useCapture:旧写法,布尔值,表示是否在捕获阶段触发
  • options:现代对象写法,用来配置监听行为

最基本用法

button.addEventListener('click', () => {
  console.log('clicked')
})

这表示给 button 注册一个点击监听器,默认在冒泡阶段执行。

第三个参数怎么理解

旧写法:布尔值

element.addEventListener('click', handler, true)
  • true 表示捕获阶段
  • false 或省略表示冒泡阶段

现代写法:对象

element.addEventListener('click', handler, {
  capture: true,
  once: true,
  passive: true
})

更推荐对象写法,因为语义更清楚,也更容易同时配置多个选项。

常见选项

capture

决定监听器是否在捕获阶段执行。

element.addEventListener('click', handler, { capture: true })

once

监听器只执行一次,执行后自动移除。

element.addEventListener('click', handler, { once: true })

适合首次引导、一次性确认逻辑。

passive

表示监听器承诺不会调用 preventDefault()

window.addEventListener('scroll', onScroll, { passive: true })

这通常用于滚动、触摸等高频事件,能帮助浏览器更积极地做性能优化。

注意:如果设置了 passive: true,就不应该再调用 preventDefault()

默认行为和传播机制的关系

addEventListener() 本身只是注册监听器,但你常会配合这些事件对象方法一起用:

  • event.preventDefault():阻止默认行为
  • event.stopPropagation():阻止继续传播
  • event.stopImmediatePropagation():阻止继续传播并阻止当前元素后续监听器

如果要系统理解传播顺序,看 frontend-event-propagation

为什么很多场景更推荐对象写法

  • 比第三个参数直接传 true/false 可读性更高
  • 可以同时表达 captureoncepassive
  • 后期维护时不容易看错监听阶段

如何移除监听器

使用 removeEventListener() 时,核心要求是:事件类型、监听函数引用,以及捕获配置要能对应上。

function handleClick() {
  console.log('clicked')
}

button.addEventListener('click', handleClick)
button.removeEventListener('click', handleClick)

一个常见坑

下面这种写法通常没法正确移除:

button.addEventListener('click', () => {
  console.log('clicked')
})

因为你没有保留函数引用,后续无法把同一个函数再传给 removeEventListener()

典型使用场景

绑定元素交互

button.addEventListener('click', submitForm)

监听页面或窗口事件

window.addEventListener('resize', handleResize)
document.addEventListener('visibilitychange', handleVisibilityChange)

事件委托

list.addEventListener('click', (event) => {
  const item = event.target.closest('li')
  if (!item) return
  console.log(item.dataset.id)
})

常见误区

  • 以为第三个参数只能传布尔值
  • 以为默认监听发生在捕获阶段,实际上默认是冒泡阶段
  • passive: true 的监听器里继续调用 preventDefault()
  • 用匿名函数绑定后,又想直接移除它
  • 只记得元素可以监听事件,忘了 windowdocumenthistory 等对象也能监听某些事件

面试或复习时的最短表达

addEventListener() 是 DOM 事件监听的核心 API,用于给事件目标注册监听器。默认监听冒泡阶段,也可以通过 capture 切到捕获阶段,并通过 oncepassive 控制监听行为。需要移除时要保留同一个函数引用。

创建于 2026/3/26 更新于 2026/5/27