自定义JS库开发:事件回调中如何同时获取Event与类实例
问题原因
当你直接把类的普通方法作为DOM事件回调传入
addEventListener时,回调运行时的this会指向触发事件的DOM元素(也就是你的dropDiv实例),而非FileUpload类的实例,因此找不到uploadFile方法。
你第二次的写法直接执行了this.dropHandler('Test'),相当于把函数运行的返回值(默认是undefined)作为回调绑定,不仅拿不到事件对象,还会在初始化阶段就提前执行逻辑,不符合预期。
可行解决方案
下面三种方案都可以同时拿到事件对象和类实例:
方案1:箭头函数包裹回调(最常用,写法简单)
利用箭头函数this继承外层作用域的特性,绑定回调时用箭头函数包裹,事件对象会自动传入回调:
class FileUpload { constructor(element) { this.element = element; this.dropDiv = document.createElement("div"); this.dropDiv.style = "border: 2px solid #007bff; background-color: lightblue; width: 100%;border-radius: 25px;"; this.dropDiv.className = "text-center"; this.dropDiv.innerHTML = "Upload<br>File<br>Here"; this.dropDiv.addEventListener("dragover", function(event) { event.preventDefault(); }); // 这里用箭头函数包裹,this指向类实例,event自动传入 this.dropDiv.addEventListener("drop", (e) => this.dropHandler(e)); this.element.appendChild(this.dropDiv); } dropHandler(event) { event.preventDefault(); // this现在指向FileUpload实例,可以正常调用uploadFile this.uploadFile("Test"); } uploadFile(file) { console.log("Logic to Upload the file or whatever..."); console.log(file); } }
如果你需要额外传自定义参数,也可以直接在箭头函数里传:
// 同时传自定义参数和事件对象 this.dropDiv.addEventListener("drop", (e) => this.dropHandler(e, '自定义参数')); // 方法接收参数 dropHandler(event, customParam) { console.log(event, customParam); this.uploadFile("Test"); }
方案2:使用bind绑定this
通过Function.prototype.bind方法,手动指定回调运行时的this指向类实例,事件对象会正常传入:
// 绑定阶段 this.dropDiv.addEventListener("drop", this.dropHandler.bind(this));
需要传自定义参数的话,bind的第二个及之后参数会作为预置参数传给回调:
// 预置自定义参数,事件对象会作为最后一个参数传入 this.dropDiv.addEventListener("drop", this.dropHandler.bind(this, '自定义参数')); // 方法接收参数 dropHandler(customParam, event) { console.log(customParam, event); this.uploadFile("Test"); }
方案3:将类方法定义为箭头函数属性
在类中直接把方法写成箭头函数属性,该方法的this会永久绑定类实例,绑定回调时可以直接传入方法:
class FileUpload { constructor(element) { // 构造器逻辑和之前一致 this.dropDiv.addEventListener("dragover", function(event) { event.preventDefault(); }); this.dropDiv.addEventListener("drop", this.dropHandler); this.element.appendChild(this.dropDiv); } // 写成箭头函数属性,this永久绑定类实例 dropHandler = (event) => { event.preventDefault(); this.uploadFile("Test"); } uploadFile(file) { console.log("Logic to Upload the file or whatever..."); console.log(file); } }
内容的提问来源于stack exchange,提问作者Phillip Gabriel
相关产品推荐
相关产品推荐

