You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法使用removeEventListener移除事件监听器的技术问题求助

问题原因

你遇到的核心问题是:Function.prototype.bind() 每次调用都会返回一个全新的函数实例。你绑定事件时用的是handleKeyDown.bind(this)生成的新函数,但移除时传入的是原handleKeyDown函数,两者引用不同,所以removeEventListener找不到对应的监听器,自然无法移除。而且每次触发绑定逻辑,都会新增一个独立的监听器,导致越积越多。

解决方法

方案1:提前保存绑定后的函数引用

在合适的作用域(比如类的实例属性、模块级变量)里存储绑定后的函数,后续添加和移除都用这个引用:

// 提前保存绑定后的函数(比如在类的构造函数或初始化逻辑里)
this.boundHandleKeyDown = this.handleKeyDown.bind(this);

// 添加监听器时用这个保存的引用
body.addEventListener('keydown', this.boundHandleKeyDown);

// 在handleKeyDown里移除时同样用这个引用
handleKeyDown(e) {
  const workoutEdit = document.querySelector('.formEdit');
  const backdrop = document.querySelector('.backdrop');
  if (e.key === 'Escape' && workoutEdit && backdrop) {
    curWorkout.parentElement.removeChild(workoutEdit);
    curWorkout.parentElement.removeChild(backdrop);
    body.removeEventListener('keydown', this.boundHandleKeyDown);
  }
  if (e.key === 'Enter') {
    this.#workouts[indexWorkout].distance = +editDistance.value;
    this.#workouts[indexWorkout].duration = +editDuration.value;
    console.log(this.#workouts);
    body.removeEventListener('keydown', this.boundHandleKeyDown);
  }
}

方案2:使用箭头函数作为回调(需保存引用)

如果你的环境支持箭头函数,也可以用箭头函数来保留this上下文,但同样要提前保存引用,避免每次生成新函数:

// 提前定义箭头函数(确保作用域正确)
this.handleKeyDown = (e) => {
  const workoutEdit = document.querySelector('.formEdit');
  const backdrop = document.querySelector('.backdrop');
  if (e.key === 'Escape' && workoutEdit && backdrop) {
    curWorkout.parentElement.removeChild(workoutEdit);
    curWorkout.parentElement.removeChild(backdrop);
    body.removeEventListener('keydown', this.handleKeyDown);
  }
  if (e.key === 'Enter') {
    this.#workouts[indexWorkout].distance = +editDistance.value;
    this.#workouts[indexWorkout].duration = +editDuration.value;
    console.log(this.#workouts);
    body.removeEventListener('keydown', this.handleKeyDown);
  }
};

// 添加监听器
body.addEventListener('keydown', this.handleKeyDown);

关键注意点

  • 一定要保证添加和移除监听器时用的是同一个函数引用,这是removeEventListener生效的核心前提。
  • 如果是在类组件场景里,别在每次渲染逻辑里直接写bind或箭头函数,否则会重复生成新函数,导致监听器越绑越多。

内容的提问来源于stack exchange,提问作者Piotr Ruszkiewicz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:42:58