【问题标题】:How to remove duplicate from addEventListener如何从 addEventListener 中删除重复项
【发布时间】:2014-02-13 01:04:57
【问题描述】:

如何从addEventListener 中删除重复项。

我的网站在用户进行某些调用时使用 ajax 填充不同的 div。我还有一个 Javascript 函数,它可以抓取所有链接并创建一个addEventListener,这样我就可以过滤 url,如果用户单击某些链接会发出警报。下面是我创建addEventListener的Javascript函数:

function supportFunction() {
   var myFunction = function(e) { 
     var regExp = new RegExp('//'+location.hostname+'($|/)');
     var href = this.href; 

     if (regExp.test(href)) {
       e.preventDefault();
       alert('same domain link');
     } 
   }
   var links = document.querySelectorAll('a');

   for (var i = 0; i < links.length; i++) {
     links[i].addEventListener('click', myFunction);
   }
}

我面临的问题是,由于在调用 supportfunction() 后使用 ajax 填充了某些内容,因此如果新填充的内容中有任何链接,则不会将其添加到 addEventListener。每当进行 ajax 调用时,我都尝试调用 supportfunction,但在这种情况下,会将重复项添加到事件侦听器中。也就是说,如果有人点击同一个域链接,他们将收到 2 个警报,在某些情况下会收到 3-4 个警报,具体取决于调用 supportfunction() 的次数。

我想我已经解释过了,我的问题是什么。如果您需要有关此问题的更多说明,请告诉我。

我尝试用谷歌搜索答案并找到此链接 http://dean.edwards.name/weblog/2005/10/add-event/ 但不知道如何在我的情况下使用它。

注意:我正在寻找纯 Javascript 解决方案而不是 jQuery 解决方案。 (我希望我在这里没有要求:))

【问题讨论】:

  • 寻找“事件委托”。不要在链接上添加事件,而是在静态父容器上添加事件,然后使用事件目标元素来确定它是否是链接。
  • 我会将 one click 事件附加到正文,然后检查 event.targetevent.srcElement。如果元素是链接(a),则执行函数。
  • 如果您不想重组整个代码以使用事件委托,请在从 ajax 调用 supportFunction 之前,在每个链接上使用旧的 myFunction 简单地调用 removeEventListener回调。
  • 我尝试将它连接到身体上,但它没有工作。我有 'event.stopPropagation 吗? event.stopPropagation() : (event.cancelBubble=true)' 在外部 div 上。

标签: javascript ajax dom-events addeventlistener event-delegation


【解决方案1】:

您希望每个链接只绑定一次事件。您可以制作一个标志来标记它是否已被事件绑定。所以代码如下。

function supportFunction() {
   var myFunction = function(e) { 
       var regExp = new RegExp('//'+location.hostname+'($|/)');
       var href = this.href; 
       if (regExp.test(href)) {
           e.preventDefault(); 
           alert('same domain link'); } 
   }
   var links = document.querySelectorAll('a');
   for (var i = 0, len = links.length; i < len; i++) {
       var link = links[i];
       // make sure add-event only once
       if(!link.getAttribute('data-added')) {
           link.setAttribute('data-added', 1);
           link.addEventListener('click', myFunction); 
       }
   }
}

【讨论】:

  • 有一个document.links集合应该比querySelectorAll更快更方便。
【解决方案2】:

如果您只添加一个侦听器而没有其他侦听器,您可以这样做:;

links[i].onclick = myFunction;

并在每次添加元素时运行该函数。这样,如果链接上已经有一个监听器,它将被 myFunction 替换。或者你可以这样做:

if (!links[i].onclick) {
  links[i].onclick = myFunction;
}

但委托可能是最好的解决方案:在所有主题链接(可能是 div)的父级上放置一个点击侦听器并测试 event target(W3C DOM 模型)或 srcElement(IE 模型)以查看是否它来自您关心的链接。

相关 MDN 文章:event.target.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2013-09-04
    • 2022-01-03
    • 2011-04-19
    • 2015-05-23
    相关资源
    最近更新 更多