前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库addEventListener once 选项 用法
浏览器事件系统

addEventListener 的 once 适合什么场景,和手动移除有何不同?

addEventListener(type, handler, { once: true }) 会在监听器第一次被调用后自动移除它。适合只处理首次交互的场景,省去在回调里手动保存并移除函数引用。

前端进阶之旅 · 一题精讲更新于 2026.09.29
浏览器#事件系统
先看核心答案读代码示例
理解线索

一次性监听器自动退场

  1. once首次调用后移除监听器
  2. removeEventListener()按事件类型与函数引用手动移除
  3. signal将监听器生命周期交给取消信号

once 只限制这个监听器调用一次,不会阻止其他监听器接收同一事件。

核心回答

先记住这个答案

once: true 让浏览器在监听器第一次执行后自动把它移除,适合“第一次点击后展示引导”或“只记录首次交互”。手动移除也能做到,但要保存原函数引用,并在正确时机调用 removeEventListener()。若组件在首次事件前就被销毁,once 不会替你提前清理,这时可用 AbortController 的 signal 或显式移除。

  • once 首次调用后自动移除
  • 手动移除要用同一函数引用
  • 监听器未触发前仍可能需要清理
  • signal 可统一取消监听

首次点击只提示一次

新功能首次使用时显示说明,后续点击走原本业务。once 能把“一次”直接声明在注册监听器处,避免回调尾部遗漏清理。

一次性引导JavaScript
const button = document.querySelector('#export')
let shown = 0
// 首次点击后,浏览器会自动移除这一条监听器
button.addEventListener('click', () => {
  shown += 1
  console.log('导出说明展示次数:', shown) // 只会输出一次
}, { once: true })

第一次点击后,这个监听器会自动退场。按钮上其他 click 监听器不受影响,也不会因为这个配置失去后续点击能力。 如果 showGuide() 自身异步执行,once 仍只控制监听器是否再次被调用,不会自动取消已经开始的异步任务。

手动移除需要引用相同

下面两次写出来的箭头函数即使代码相同,也不是同一个函数对象。removeEventListener("click", () => showGuide()) 无法移除先前注册的箭头函数。要手动清理,应把处理函数保存为变量。

还要注意移除匹配时的捕获配置。多个相同类型监听器若分别在捕获与冒泡阶段注册,清理时应对应阶段。页面或组件销毁前尚未触发的 once 监听器,可用 signal 一次取消,避免长期挂在仍存活的目标上。

例如弹窗打开后只等用户按下一次 Escape,若用户先点关闭按钮,那个键盘监听就永远等不到 Escape。把监听注册时的 signal 与弹窗生命周期绑定,关闭时调用 abort(),才能覆盖“事件发生”和“组件先消失”两条结束路径。once 解决次数,signal 解决提前清理,职责不同。

once 的“一次”是监听器被调用一次,不是业务成功一次。回调里校验失败、提前 return,浏览器也已移除监听器。需要“直到输入合法才停止监听”时,应自己保存处理函数并在成功分支调用 removeEventListener()。

回答前,多想一步

容易答错的地方

以为 once 会让事件只发生一次
它只让这一条监听器执行一次,事件本身和其他监听器照常运行。
用新箭头函数尝试手动移除
函数引用不同,旧监听器不会被移除。
试着用自己的话回答

面试官还会怎么问?

监听器从未触发,once 会自动清理吗?

不会仅因时间过去就退场;目标生命周期结束或主动移除时才结束等待。

once 和 signal 能一起用吗?

可以。触发一次后自动移除,或在触发前调用 abort() 主动取消。

once 监听器里抛错会怎样?

它仍是一次性监听器;不应把“异常后重试”寄托在下一次同一监听器调用上。

从一道题,走向一组知识

把知识连起来

事件系统

click 事件里的 clientX、pageX、screenX 分别从哪里量?

首次点击处理仍需理解 click 的坐标来自哪个坐标系。

事件系统

click 和 mousedown、mouseup 的触发时机有什么差别?

once 监听 click 与监听 mousedown 的触发时机不同。

参考资料

  • MDN 参考文档

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 首次点击只提示一次
  3. 手动移除需要引用相同
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑