无法移除EventListener:TypeScript中鼠标移动事件监听删除失败
鼠标指针锁定解除后无法移除mousemove监听器的问题解决
你的问题核心在于**Function.prototype.bind()每次调用都会返回一个全新的函数实例**。你在注册监听器时用了this._handleMouseMovement.bind(this),解除锁定时又调用了一次相同的bind语句——这两个函数看起来功能一样,但在内存里是完全不同的引用,所以removeEventListener找不到要移除的那个监听器,导致它一直生效。
解决方案:提前绑定并复用函数引用
我们可以在类的构造函数里提前把_handleMouseMovement绑定好上下文,存为一个实例属性,之后注册和移除监听器都用这个属性,保证引用一致。
修改后的代码如下:
class MyClass { let canvas: any; // 新增:存储绑定好上下文的处理函数 private _boundMouseMovementHandler: (event: MouseEvent) => void; constructor(canvas: any) { this.canvas = canvas; // 提前绑定并保存函数引用 this._boundMouseMovementHandler = this._handleMouseMovement.bind(this); this.canvas.onclick = this._mouseClickHandler.bind(this); document.addEventListener('pointerlockchange', this._togglePointerLock.bind(this), false); } private _mouseClickHandler(event: MouseEvent): void { this.canvas.requestPointerLock(); } private _togglePointerLock() { if (document.pointerLockElement === this.canvas) { console.info('Locked mouse pointer to canvas.'); // 使用提前绑定好的函数引用 document.addEventListener('mousemove', this._boundMouseMovementHandler, false); } else { console.info('Unlocked mouse pointer from canvas.'); // 移除时用同一个引用 document.removeEventListener('mousemove', this._boundMouseMovementHandler, false); } } private _handleMouseMovement(event: MouseEvent) { console.log('Mouse moved to: ', event.movementX, event.movementY); } }
额外优化提示
你原来代码里的这两行其实是多余的,可以删掉:
this.canvas.requestPointerLock = this.canvas.requestPointerLock; document.exitPointerLock = document.exitPointerLock;
这两个方法本来就是DOM元素和document的原生方法,重新赋值不会有任何作用,反而会增加代码冗余。
内容的提问来源于stack exchange,提问作者チーズパン
相关产品推荐
相关产品推荐

