JavaScript类中添加的事件监听器正确移除方法,如何保留类实例this指向?
核心实现逻辑
你遇到的问题本质是事件监听要求添加和移除的必须是同一个函数引用,同时要保证函数执行时this指向类实例,所以只要把绑定了正确this的函数提前存储到实例属性上,添加和移除都使用这个存储的引用即可。同时注意DOM事件名统一为全小写,不要写成驼峰mouseDown,大小写不匹配也会导致移除失败。
方案1:构造函数内手动bind绑定并存储引用
兼容性最好,无需依赖新语法支持:
class TestClass { constructor() { this.storedValue = "In class"; // 提前把方法绑定this后存到实例属性,保证引用唯一 this.boundMouseDown = this.mouseDown.bind(this); document.addEventListener("mousedown", this.boundMouseDown); } test() { console.log(this); } mouseDown() { console.log(this); // 指向TestClass实例 // 移除时用同一个绑定后的引用 document.removeEventListener("mousedown", this.boundMouseDown); } } const test = new TestClass();
方案2:使用类公共字段箭头函数(ES2022+支持)
写法更简洁,类字段定义的箭头函数会自动绑定当前实例为this,不需要手动bind,引用天然唯一:
class TestClass { storedValue = "In class"; constructor() { document.addEventListener("mousedown", this.mouseDown); } test() { console.log(this); } // 箭头函数类字段,this自动绑定实例 mouseDown = () => { console.log(this); // 指向TestClass实例 document.removeEventListener("mousedown", this.mouseDown); } } const test = new TestClass();
方案3:实现EventTarget的handleEvent接口
DOM标准自带的原生方案,不需要额外绑定this,只要类实现了handleEvent方法,addEventListener可以直接传类实例作为回调,事件触发时会自动调用实例的handleEvent方法,this天然指向实例:
class TestClass { constructor() { this.storedValue = "In class"; // 直接传实例作为回调 document.addEventListener("mousedown", this); } test() { console.log(this); } // 实现标准handleEvent方法,可根据事件类型分发不同处理逻辑 handleEvent(e) { if(e.type === 'mousedown') { this.mouseDown(); } } mouseDown() { console.log(this); // 指向TestClass实例 // 移除时直接传实例即可 document.removeEventListener("mousedown", this); } } const test = new TestClass();
内容的提问来源于stack exchange,提问作者Gregory William Bryant
相关产品推荐
相关产品推荐

