Wie entferne ich EventListener, das ist AddEventListener mit anonymer Funktion?

87
function doSomethingWith(param)
{
    document.body.addEventListener(
        'scroll',
        function()
        {
            document.write(param);
        },
        false
    ); // An event that I want to remove later
}
setTimeout(
    function()
    {
        document.body.removeEventListener('scroll', HANDLER ,false);
            // What HANDLER should I specify to remove the anonymous handler above?
    },
    3000
);
doSomethingWith('Test. ');
Japboy
quelle
Mögliches Duplikat von JavaScript: Ereignis-Listener entfernen
Heretic Monkey

Antworten:

109

Das kannst du nicht. Sie müssen eine benannte Funktion verwenden oder die Referenz irgendwie speichern.

var handler;

function doSomethingWith(param) {
    handler = function(){
        document.write(param);
    };  
    document.body.addEventListener('scroll', handler,false);
}
setTimeout(function() {
     document.body.removeEventListener('scroll', handler ,false);
}, 3000);

Am besten tun Sie dies strukturiert, damit Sie verschiedene Handler identifizieren und entfernen können. Im obigen Beispiel konnten Sie natürlich nur den letzten Handler entfernen.

Aktualisieren:

Sie können Ihren eigenen Handler-Handler erstellen (:)):

var Handler = (function(){
    var i = 1,
        listeners = {};

    return {
        addListener: function(element, event, handler, capture) {
            element.addEventListener(event, handler, capture);
            listeners[i] = {element: element, 
                             event: event, 
                             handler: handler, 
                             capture: capture};
            return i++;
        },
        removeListener: function(id) {
            if(id in listeners) {
                var h = listeners[id];
                h.element.removeEventListener(h.event, h.handler, h.capture);
                delete listeners[id];
            }
        }
    };
}());

Dann können Sie es verwenden mit:

function doSomethingWith(param) {
    return Handler.addListener(document.body, 'scroll', function() {
        document.write(param);
    }, false);
}

var handler = doSomethingWith('Test. ');

setTimeout(function() {
     Handler.removeListener(handler);
}, 3000);

DEMO

Felix Kling
quelle
Können Sie erklären, wie der strukturierte Weg ist? Meine Englischkenntnisse sind nicht gut genug, um das zu verstehen ... Danke.
Japboy
1
@ Japboy: Gern geschehen :) Ich habe gerade einen kleinen Fehler bemerkt und ihn behoben.
Felix Kling
Warum sollten Sie den addListener und den removeListener umschließen?
nutzlos
@useless: Meinst du die selbstaufrufende Funktion? Zu halten iund listeners"privat".
Felix Kling
2
@Bergi: Fertig. Lassen Sie mich wissen, wenn ich etwas verpasst habe.
Felix Kling
11

Sie können nicht, Sie benötigen einen Verweis auf die Funktion:

function doSomethingWith(param) {
   var fn = function(){ document.write(param); };
   document.body.addEventListener('scroll', fn, false);
   setTimeout(function(){ document.body.removeEventListener('scroll', fn, false); }, 3000);
}
doSomethingWith('Test. ');
David
quelle
Wie übergibst du ein Ereignisobjekt?
Slier
@sliervar fn = function(event){ document.write(param); };
Cychoi
5

Sie können dies auch so tun:

const ownAddEventListener = (scope, type, handler, capture) => {
  scope.addEventListener(type, handler, capture);
  return () => {
    scope.removeEventListener(type, handler, capture);    
  }
}

Dann können Sie den Ereignis-Listener folgendermaßen entfernen:

// Add event listener
const disposer = ownAddEventListener(document.body, 'scroll', () => { 
  // do something
}, false);

// Remove event listener
disposer();
Simon Jentsch
quelle
Ist es möglich festzustellen, welche Ereignisse auf diese Weise an das Objekt gebunden wurden?
Frumbert
Sie können der Funktion einfach einige Eigenschaften hinzufügen, z. B. Typ, Umfang usw.const disposerFn = () => { scope.removeEventListener(type, handler, capture); } disposerFn.type = type; return disposerFn;
Simon Jentsch,
1

Wenn Sie den IE nicht unterstützen müssen, können Sie die Option einmal verwenden

[Element].addEventListener('click', () => {...}, {
  capture: false,
  once: true
});
Manoi
quelle