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

为何我的事件监听器无法被正确移除?

问题根源

你这段代码的核心问题是:每次调用zoom方法时,都会重新创建onMouseDown、onMouseMove、onMouseUp三个新的箭头函数实例。而removeEventListener要求传入的函数引用必须和添加时的完全一致,所以你后续调用zoom(false)时,传入的是新创建的函数,自然找不到之前添加的监听,导致移除失败。

解决方案

把事件处理函数定义为类的成员属性,确保整个实例生命周期内只存在一个函数引用,这样添加和移除时用的是同一个函数,就能正常生效了。下面提供两种实现方式:

方式1:使用箭头函数作为类成员(推荐,自动绑定this)

箭头函数会自动捕获类实例的this,无需手动绑定,而且作为类属性只会初始化一次:

class YourClass {
  // 将事件处理函数定义为类的私有成员属性
  private onMouseDown = (event: MouseEvent) => {
    /* 你的原有代码 */
  };

  private onMouseMove = (event: MouseEvent) => {
    /* 你的原有代码 */
  };

  private onMouseUp = () => {
    /* 你的原有代码 */
  };

  public zoom(dragZoomActive: boolean): void {
    if (dragZoomActive) {
      window.addEventListener('mousedown', this.onMouseDown, true);
      window.addEventListener('mousemove', this.onMouseMove, true);
      window.addEventListener('mouseup', this.onMouseUp, true);
    } else {
      window.removeEventListener('mousedown', this.onMouseDown, true);
      window.removeEventListener('mousemove', this.onMouseMove, true);
      window.removeEventListener('mouseup', this.onMouseUp, true);
    }
  }
}

方式2:普通函数+构造函数bind绑定

如果更习惯用普通函数,可以在类的构造函数中提前绑定this,确保每次调用都是同一个函数实例:

class YourClass {
  constructor() {
    // 在构造函数中绑定this,固定函数引用
    this.onMouseDown = this.onMouseDown.bind(this);
    this.onMouseMove = this.onMouseMove.bind(this);
    this.onMouseUp = this.onMouseUp.bind(this);
  }

  private onMouseDown(event: MouseEvent): void {
    /* 你的原有代码 */
  }

  private onMouseMove(event: MouseEvent): void {
    /* 你的原有代码 */
  }

  private onMouseUp(): void {
    /* 你的原有代码 */
  }

  public zoom(dragZoomActive: boolean): void {
    if (dragZoomActive) {
      window.addEventListener('mousedown', this.onMouseDown, true);
      window.addEventListener('mousemove', this.onMouseMove, true);
      window.addEventListener('mouseup', this.onMouseUp, true);
    } else {
      window.removeEventListener('mousedown', this.onMouseDown, true);
      window.removeEventListener('mousemove', this.onMouseMove, true);
      window.removeEventListener('mouseup', this.onMouseUp, true);
    }
  }
}
关于bind传参的疑问

你之前担心用bind会影响event参数的传递——其实完全不用怕。bind只是修改函数的this指向,不会影响函数原本的参数接收。当事件触发时,浏览器依然会自动把MouseEvent参数传给你的处理函数,和之前箭头函数的用法完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:22:47