【问题标题】:Is it possible to extend the EventTarget interface?是否可以扩展 EventTarget 接口?
【发布时间】:2013-10-27 09:30:10
【问题描述】:

如果可能,我正在寻找答案,甚至是一个好主意。

通常,作为 IE8 和更早版本的修复程序,使用类似于此的解决方法:

var addEvent = function(obj, e, cb) {
    if(obj.attachEvent) {
        return obj.attachEvent('on' + e, cb);
    } else {
        obj.addEventListener(e, cb, false);
        return true;
    }
}

然后程序员总是使用addEvent 而不是addEventListener

是否有任何方法或要点来创建一个 addEventListener 函数,当它未定义时会环绕 attachEvent

我想这有点棘手,因为 EventTarget 可以是 DOM 元素、文档、窗口或其他东西。

【问题讨论】:

    标签: javascript dom-events addeventlistener


    【解决方案1】:

    这取决于你想回多远。在 IE8 上,您可以扩展 Element.prototype 以向所有 HTML 元素添加功能,这至少完成了 90% 的工作。我相当肯定你不能在 IE6 中做到这一点(PrototypeJS 不得不求助于扩展单个 Element 实例),我不记得 IE7。不过,除非您的目标是东亚市场,否则您基本上可以忽略 IE7 及更早版本。

    以下是您如何执行此操作的示例:

    (function() {
      // Functions for IE
      function stopPropagation() {
        this.cancelBubble = true;
      }
      function preventDefault() {
        this.returnValue = false;
      }
      function addEventUsingAttach(eventName, handler)
      {
        this.attachEvent("on" + eventName, function() {
          var e = window.event;
          e.stopPropagation = stopPropagation;
          e.preventDefault = preventDefault;
          handler.call(this, e);
        });
      }
    
      // Function to add `addEvent` to the given target object
      function extendIt(target)
      {
        if (target.addEventListener) {
          target.addEvent = Element.prototype.addEventListener;
        }
        else {
          target.addEvent = addEventUsingAttach;
        }
      }
    
      // Add it to `Element.prototype` if we have it
      if (typeof Element !== "undefined" &&
          typeof Element.prototype !== "undefined") {
        extendIt(Element.prototype);
      }
    
      // Add it to `window` and `document` (etc.)
      extendIt(window);
      extendIt(document);
    })();
    

    Live Example | Source

    然后您手动扩展其他 EventTargets,例如 windowdocument(参见上面代码清单的末尾)。


    原始答案:我最初误解了您的问题是关于添加 addEventListener,特别是在 IE8 上,而实际上您的问题很明显不是关于添加,但添加您自己的addEvent。我将把这个答案留给其他读者:

    这取决于你想回多远。在 IE8 上,您可以扩展 Element.prototype 以向其添加 addEventListener,这将被页面上的所有 HTML 元素使用(见下文)。但是,您添加的 shim 不支持捕获阶段,因为 IE 不支持它,直到它们原生支持 addEventListener。我很确定你不能在早期版本(IE7、IE6)上扩展Element.prototype,PrototypeJS 不得不退回到为旧版本的 IE 扩展特定元素。但它适用于 IE8。

    扩展了Element.prototype,那么您必须手动扩展您提到的其他事件目标,但扩展Element.prototype 可以完成大部分工作。

    但是,如果您这样做并包含第三方脚本,请注意它们可能会假定 addEventListeneer 的正确实现已完成捕获阶段。

    这是将addEventListener 添加到 IE8 的基本 shim:

    (function() {
      function stopPropagation() {
        this.cancelBubble = true;
      }
      function preventDefault() {
        this.returnValue = false;
      }
      if (typeof Element !== "undefined" &&
          typeof Element.prototype !== "undefined" &&
          !Element.prototype.addEventListener) {
        Element.prototype.addEventListener = function(eventName, handler, useCapture) {
          if (useCapture) {
            throw "Browser doesn't support capturing phase";
          }
          this.attachEvent("on" + eventName, function() {
            var e = window.event;
            e.stopPropagation = stopPropagation;
            e.preventDefault = preventDefault;
            handler.call(this, e);
          });
        };
      }
    })();
    

    Live Example | Source

    【讨论】:

    • 其实 T.J.我最初的意思是我可以只包含类似你的 IE8 脚本(我完全忽略它之前的版本),然后正常使用addEventListener(而不在 IE8 中捕获)。关键是要避免使用一个独特命名的 addEvent,而是使用基于标准的 vanilla JS。
    【解决方案2】:

    通常,可以通过将函数附加到对象来将函数添加到对象

    obj.addEventListener = function(/* args*/) { /* body */ }
    

    或者通过将函数附加到对象构造函数的原型上

    EventTarget.prototype.addEventListener = function(/* args*/) { /* body */ }
    

    使用前者,添加的函数只能在特定对象上调用,而后者允许您在所有对象上调用该函数,这些对象是从该特定对象构造函数创建或将创建的。

    然而,

    • EventTargets 是宿主对象,因此是否可以将函数添加到此类对象取决于实现。
    • EventTargets 是宿主对象,因此 EventTarget.prototype 是否实际存在以及是否与原生对象具有相同的含义取决于实现。
    • 如果一个对象遵循EventTarget 接口,它很可能已经有一个addEventListener 函数。
    • attachEvent 附加的事件侦听器与addEventListener 附加的事件侦听器具有不同的参数。

    最后,尝试让具有糟糕 DOM 的浏览器使用 JavaScript 支持更多符合标准的浏览器是不可行的。

    【讨论】:

    • typeof EventTarget 即使在 Chrome 上也是 "undefined",更不用说 IE8。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多