JavaScript的匿名函数中的removeEventListener

3
我该如何移除这个事件监听器?我尝试了以下代码,但似乎没有任何效果。
class Tag {
  constructor(name){
      this.tag = document.createElement(name);
  }
      removeEvent(e,func){
      this.tag.removeEventListener(e,func,false);
  }
      addEvent(e,func) {
      this.tag.addEventListener(e,func,false);
  }

}

let tag = new Tag();
tag.addEvent('click',(e)=> {
   console.log('something');
});

如何使removeEvent工作?请帮忙,我需要知道如何引用匿名函数。因为这个是有效的。

 function handler(e){
     // code for event
 }

 tag.addEventListener('click',handler,false);  
 tag.removeEventlistener('click',handler,false);

我尝试添加了

标签。

  removeEvent(e,func) {
      func.ref = function (){
          return arguments.callee;
      }

      this.tag.removeEventListener(e,func.ref,false);

  }

现在我们将引用func.ref作为函数引用,但它目前无法正常工作。


我认为你不能这样做,除非保存一个事件处理程序的引用以便将其传递给removeEventListener - Thiatt
如果你一直追踪下去,jQuery的off()方法附加到这个jQuery.event.remove(),然后做其他事情。最终,它以你尝试的removeEventListener()调用结束。不过,句柄来自privData,所以我猜他们在某个地方保持引用,这样它就可以稍后传递。 - Jared Farrish
4个回答

3
我曾在编写一个扩展程序时遇到了同样的问题。我通过添加一个新的监听器来解决这个问题,该监听器在事件到达我想要删除的监听器/函数之前捕获/停止了所有传播。
window.addEventListener(type, function (event) {
    event.stopPropagation();
}, true);

Credit: StackOverflow


这帮了我 :) - Akashxolotl

2

简单的删除匿名事件监听器方法

我找到了一种简单而好用的方法来删除使用匿名函数的事件监听器,只需将以下两个函数添加到您的代码中:

let events = new Map();
function addListener(element, event, callback, id) {
    events.set(id, callback);
    element.addEventListener(event, callback);
}

function removeListener(element, event, id) {
    element.removeEventListener(event, events.get(id));
    events.delete(id);
}

匿名函数非常适合保持this上下文,并且没有找到一个好的方法来同时拥有this和删除事件监听器的能力。

示例

let events = new Map();

function addListener(element, event, id, callback) {
  events.set(id, callback);
  element.addEventListener(event, callback);
}

function removeListener(element, event, id) {
  element.removeEventListener(event, events.get(id));
  events.delete(id);
}


let btn = document.getElementById('btn');
let cpt = 1;
addListener(btn, 'click', 'btnClick', e => {
  btn.innerHTML = `x${++cpt}`;

  if (cpt === 3) {
    removeListener(btn, 'click', 'btnClick');
  }
});
<button id="btn">x1</button>


1

匿名函数无法被删除,因为它们没有存储带有可供您的代码访问的标识符。这就是为什么称它们为“匿名”的原因,也是使用它们的缺点之一。另一个缺点是无法直接为它们编写单元测试。它们的好处是因为它们不被存储,所以可以节省一点内存。此外,作为一种函数式编程语言,JavaScript 允许将匿名函数轻松地传递为数据(尽管您当然可以传递命名的函数引用)。


谢谢大家的帮助,我决定使用这种方式来跟踪对象标签中的事件:this.events['event_name'].click_0 = func; 这样,我可以通过对象引用删除事件,例如tag.removeEvent(tag.events.click.click_0)。整数click_[int]会随着我创建相同类型的新事件而附加一个循环计数器。 - Breimer

0

很遗憾,目前没有办法删除作为监听器附加的匿名函数。

您可以使用一个小技巧,每次存储传递进来的函数并跟踪所有事件,然后使用“缓存”的事件监听器来检索它们并分离事件。

这里是一个示例草稿:

var events = [];

function storeEvent(id, fn, useCaptureMode, event) {
 var e = findStoredEvent(id, event, useCaptureMode);
  if (!e) {
   events.push({id, fn, useCaptureMode, event});
  }
}

function findStoredEvent(id, event, useCaptureMode) {
 return events.find(el => el.id === id && el.event === event && el.useCaptureMode === el.useCaptureMode);
}

document.getElementById("test").addEventListener('click', function() {
 storeEvent(this.id, arguments.callee, false, 'click');
 console.log('test');
}, false);

function detachEvent() {
 var e = findStoredEvent('test', 'click', false);
  if (e) {
  document.getElementById("test").removeEventListener(e.event, e.fn, e.useCaptureMode);
    events.splice(events.findIndex(el => el === e), 1);
  } 
}
<button id="test">
  Test
</button>
<button id="remove" onclick="detachEvent()">
  Remove Event
</button>

希望它有所帮助


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