3 Stimmen

Muss ich Ereignisse aus dem DOM löschen, wenn ein Element entfernt wird?

Nehmen wir an, ich habe eine Seite, die Seiten dynamisch lädt. Während jede Seite in das DOM geladen wird, werden Ereignisse für die Elemente auf dieser Seite hinzugefügt.

Wenn der Benutzer eine andere Seite lädt, werden die zuvor geladenen Elemente aus dem DOM entfernt. Da die Elemente selbst nicht mehr existieren, funktionieren natürlich auch die diesen Elementen zugeordneten Ereignisse nicht mehr.

Aber werden sie auch entfernt? Oder verbleiben sie im Speicher des Benutzers und nehmen dort Platz weg?

Nachbereitung: Wurde eine Funktion als solche definiert:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

Man könnte das Ereignis leicht entfernen mit event = null (oder so würde ich annehmen!)...

aber was wäre, wenn das Ereignis nicht in einer lokalen Variablen gespeichert würde?

$('foobar').addEvent('click', function() {
    alert(1);
});

Danke!

1voto

magritte Punkte 7078

Interessante Frage... lesen Sie das hier: https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

Um den Ereignis-Listener mit jQuery zu entfernen, siehe http://api.jquery.com/unbind/

1voto

Porco Punkte 4055

Ich habe festgestellt, dass ältere Versionen von IE Probleme mit dem Hinzufügen und Entfernen von vielen Elementen mit Ereignissen, die an sie gebunden sind, zu haben scheint. Die Hauptursache sind zirkuläre Verweise, die nicht in den Müll geworfen werden können. Weitere Informationen finden Sie hier: http://msdn.microsoft.com/en-us/library/Bb250448

Durch das Setzen auf null wird das Ereignis nicht entfernt, sondern nur der Verweis auf das Ereignis. Sie müssen sowohl element.removeEventListener und element.detachEvent (je nach Browser) zu verwenden, oder wenn Sie mit Jquery unbind sollte funktionieren.

Es gibt auch Tools zum Aufspüren von Lecks, dieses hier funktioniert gut (laut einem Mitarbeiter): http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

1voto

Dimitar Christoff Punkte 26084

Zunächst einmal: Was? Das ergibt keinen Sinn:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

Es speichert das Ereignis nicht in einer lokalen Variablen, wie Sie zu glauben scheinen, sondern einen Verweis auf die foobar element object in die event Variable - die meisten Mootools-Elementmethoden geben this für die Verkettung, also das Element selbst und nicht das Ergebnis der Methode (es sei denn, es handelt sich um einen Getter wie '.getStyle').

es hängt dann davon ab, wie man das Element loswird, was als nächstes passiert. erstens, element.destroy finden Sie hier: https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728

es wird das Element aus dem Dom und aus dem Speicher entfernen und es auf eine sichere Weise leeren. es wird auf die GC des Browsers angewiesen sein, um aufzuräumen, sobald es weg ist, mootools wird keine spektakuläre GC für Sie für das Element selbst tun, aber es führt die spezielle clean Funktion auch auf die untergeordneten Knoten anwenden: var children = clean(this).getElementsByTagName('*'); .

Die Clean-Methode beseitigt auch alle Event-Handler und Speicher, die mit den untergeordneten Elementen des Divs verbunden sind.

DANN werden die von mootools hinzugefügten Ereignisse im Elementspeicher abgelegt. Der Elementspeicher befindet sich in einem Objekt hinter einem Abschluss, den das Elementproto verwendet. Um es zu testen, werden wir es neu implementieren und es durchstoßbar machen (ein globales Objekt namens storage), so dass wir überprüfen können, was mit der Referenz passiert, nachdem das Elternteil weg ist:

http://jsfiddle.net/dimitar/DQ8JU/

(function() {
    var storage = this.storage = {}; // make it puncturable

    var get = function(uid){
        return (storage[uid] || (storage[uid] = {}));
    };

    Element.implement({
       retrieve: function(property, dflt){
            var storage = get($uid(this)), prop = storage[property];
            if (dflt != null && prop == null) prop = storage[property] = dflt;
            return prop != null ? prop : null;
        },

        store: function(property, value){
            var storage = get($uid(this));
            storage[property] = value;
            return this;
        },

        eliminate: function(property){
            var storage = get($uid(this));
            delete storage[property];
            return this;
        }

    });

})();

// read it.
var link = document.getElement("a");
var uid = link.uid; // will reference the mootools unique id for it

// add an event handler
link.addEvent("click", function(e) {
    console.log("hi");
    this.destroy();
    // see what's left in storage for that element.
    console.log(storage[uid]);

    // storage should be empty.
    console.log(storage);
});

link.getFirst().addEvent("mouseenter", function() {
   console.log("over");
});

// check to see if it is there via element storage API.
console.log(link.retrieve("events").click);

// check to see if it's there via our puncture
console.log(this.storage[uid]);

// see all events in storage, inc child element:
console.info(this.storage);

was all dies beweist, ist, mootools bereinigt alles, was Sie brauchen gereinigt. solange Sie keine inline verwenden onclick= Elemente, mit denen Sie arbeiten, werden Sie gut zurechtkommen. Zwischen mootools' Garbage Collection und der Browser, Sie sind gut abgedeckt. nur bewusst sein, können Sie stapeln mehrere Ereignisse auf einem einzigen Element, wenn die Rückrufe anonym sind.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X