首页 > 解决方案 > 带有包装监听器的 AddEventListener

问题描述

每当触发点击事件时,我都会尝试运行自定义代码。这是我到目前为止所拥有的:

const origHandler = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function (eventName, eventHandler, options) {
    let handler = eventHandler;
    const target = this;
    origHandler.call(this, eventName, function (e) {
        // Do something with e
        doSomething(e);
        // Run original function
        handler.call(target, e);
    }, options);
};

我也在使用这个多选下拉插件。使用上面的代码,单击下拉元素不会做任何事情,直到我单击它几次。如果我只执行以下操作,它就可以正常工作:

    origHandler.call(this, eventName, handler, options);

但是,上述内容不允许我在调用处理程序时运行自定义代码。我能做些什么来创建一个也适用于这些类型插件的包装器吗?

此问题并非特定于此插件,因为我已经看到应用程序中的其他一些插件也因此代码而中断。

标签: javascript

解决方案


不完整的算法

发布的代码调用(原始)addEventListener带有匿名函数参数。这意味着任何作为其函数参数removeEventListener提供的调用代码都将失败 - 它永远不会与匿名函数匹配。handler

要成功添加一个钩子addEventListener,需要实现一个互补的钩子removeEventListener和额外的逻辑,以实现正确删除添加的侦听器。

这并不意味着遇到的特定问题是专门由打补丁引起的addEventListener,但这样做肯定会产生代码故障。

一般来说prototype,如果可能的话,最好避免修补全局函数的对象属性。

替代使用捕获

在包含任何库脚本之前,添加一个使用事件捕获的文档点击事件侦听器,应该允许在被其他任何东西处理之前检查每个点击事件:

document.addEventListener("click", function(e){
       // do something with event
         console.log("click event type: %s on %s", e.type, e.target.tagName);
    }, {capture:true});
body {background-color: white}
html {background-color: grey}
Click me!


推荐阅读