为新元素添加addEventListener函数

4
考虑一个基本的addEventListener,如下:
window.onload=function(){
  document.getElementById("alert")
  .addEventListener('click', function(){
     alert("OK");
  }, false);
}

当我们从外部源通过 AJAX 调用一个原始文档中不存在的 <div id="alert">ALERT</div> 时,如何强制让 addEventListener 对文档中新添加的元素起作用(在 window.onload 初始扫描 DOM 元素之后)?
在 jQuery 中,我们使用 live()delegate() 来实现这一点;但是,在纯 JavaScript 中,我们该如何使用 addEventListener 实现呢?事实上,我正在寻找与 delegate() 等效的方法,因为 live() 将事件附加到根文档;我希望在 parent 层面上进行新的事件监听。
2个回答

5

这段代码虽然与jQuery的事件系统有很大差别,但基本思路是相同的。

http://jsfiddle.net/fJzBL/

var div = document.createElement("div"),
    prefix = ["moz","webkit","ms","o"].filter(function(prefix){
         return prefix+"MatchesSelector" in div;
    })[0] + "MatchesSelector";

Element.prototype.addDelegateListener = function( type, selector, fn ) {

    this.addEventListener( type, function(e){
        var target = e.target;

        while( target && target !== this && !target[prefix](selector) ) {
            target = target.parentNode;
        }

        if( target && target !== this ) {
            return fn.call( target, e );
        }

    }, false );
};

您错过的内容包括:
  • 性能优化。每个委托监听器都将运行一个完整的循环,因此如果您在单个元素上添加了许多委托监听器,您将运行所有这些循环。
  • 无法编辑事件对象。因此,您无法修复非常重要的e.currentTarget,因为this通常用作对某个实例的引用。
  • 没有数据存储实现,因此没有好的方法来删除处理程序,除非您手动编写函数。
  • 仅支持冒泡事件,因此没有"change""submit"等,您可能认为这些是jQuery的基本功能。
  • 还有许多其他问题,我暂时忘记了。

非常有趣的观点,我学到了很多,但我认为jQuery的delegate()也或多或少有这些缺点。 - Googlebot
@Ali,这些缺点是 jQuery 特别没有的。 - Esailija

2
document.addEventListener("DOMNodeInserted", evtNewElement, false);

function evtNewElement(e) {
    try {
        switch(e.target.id) {
            case 'alert': /* addEventListener stuff */ ; break;
            default: /**/
        }
    } catch(ex) {}
}

注意:根据@hemlock的评论,似乎这种事件系列已被弃用。我们必须转向使用变动观察器


1
注意:变异事件在Level 3 DOM中已被弃用。http://www.w3.org/TR/DOM-Level-3-Events/#event-type-DOMNodeInserted - Hemlock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接