2016-02-17 7 views
10

Ich habe eine große Single-Page-Anwendung erstellt und vor kurzem in Memory-Lecks in JS untersucht. Und ich denke, ich habe ein Speicherleck, weil ich - da ich die Profile (Snapshot) -Funktion in Chrome verwende - sehe, dass ich viele abgelöste DOM-Elemente habe.Was ist die richtige Methode, um Ereignislistener zu lösen und untergeordnete Elemente in Einzelseitenanwendungen zu entfernen?

Hier ist eine vereinfachte Ansicht meines Setup:

<div id="container"> 
    <div class="buttons"> 
    <a class=".btn" href="/someurl/"> Button A</a> 
    <a class=".btn" href="/someurl/"> Button B</a> 
    <a class=".btn" href="/someurl/"> Button C</a> 
    </div> 

    <div class="ajaxHolder"></div> 
</div> 

Also, wenn ein Benutzer der Taste A klickt, zum Beispiel, würde ich einen AJAX-Aufruf verwenden, um Inhalte in die .ajaxHolder zu laden. Etwas wie folgt aus:

//This is the content... 
<div class="contentA"> 
    <p>some text...</p> 
    <input type="checkbox" class="checkbox"> 
    <input type="checkbox" class="checkbox"> 
    <input type="checkbox" class="checkbox"> 
    <input type="checkbox" class="checkbox"> 
</div> 

Ich habe auch zwei Funktionen in meinem MAIN Skriptdatei. Einer wäre so:

//Click event bound to a.btn which tigger the ajax call 
$(.buttons).on('click', '.btn', function(){ 
    //Do ajax here... 
    //on success... 
    var holder = $(".ajaxHolder"); 
    holder.children().off().remove(); // Is this the way to do this?? 
    holder.off().empty(); //I don't think I need .off() here, but I guess it can't hurt... 
    holder.append(ajaxSuccessData); 
}); 

So weit so gut. Aber jetzt mit dem Inhalt geladen, ich habe diese Funktion auch in meinem MAIN Skriptdatei:

//So here, I am binding an event to the checkboxes... 
$(".ajaxHolder").on('change', '.checkbox', function(){ 
    //Do something... 
}); 

So, jetzt, wenn der Benutzer den Knopf B drückt, beispielsweise .ajaxHolder geleert, aber alle diese Ereignisse gebunden an meine Checkboxen scheinen zu bleiben, weil sie in meinem freistehenden DOM-Baum auftauchen.

Was fehlt mir hier? Wie kann ich sicherstellen, dass ich keine getrennten DOM-Elemente in einer einzelnen Seitenanwendung habe, die so läuft?

BONUS FRAGE: Ich habe eine Menge von Veranstaltungen wie diese gebunden:

$(".ajaxHolder").on('someEvent...','.someClass....', someFunction()); 

Das heißt, alles ist immer an meiner .ajaxHolder, weil ich Ereignis Delegation verwenden, da .ajaxHolder wird immer existieren - während andere Elemente, die geladen werden, nicht immer existieren werden, so kann ich nicht einfach $(button).on('click')..., etc.

So ist dies der richtige Weg, dies auch zu tun? Gibt es ein Limit dafür, wie viele Dinge ich an diese .ajaxHolder anhängen kann oder gibt es keine Probleme damit?

EDIT: Hier ist ein Bild von meiner Konsole, wenn das überhaupt hilft.

enter image description here

+2

Entfernen des Elements mit einer jQuery-Methode ist mehr als genug, um alle damit verbundenen Daten zu entfernen, solange die Daten mit jQuery zugeordnet wurden. Sie müssen Ereignisse nicht manuell lösen. –

+0

Sie können Delegation auf dem AjaxHolder alles tun, was Sie wollen, aber ich finde, dass leicht aus dem Ruder laufen, wenn das Projekt wächst. Es kann auch beginnen, die Leistung zu beeinträchtigen, wenn viele Event-Handler an denselben Typ gebunden sind. Sie werden jedoch wahrscheinlich lange vor dem Auftreten dieses Leistungsproblems auf Probleme mit der Wartbarkeit stoßen. –

+0

@KevinB Also, warum erscheinen die gelösten dom Elemente? Gibt es noch eine andere Ursache, die einen Verweis auf Elemente enthält, die entfernt wurden? Und für den zweiten Teil, welche andere Option habe ich, außer es an den AjaxHolder delegieren ... Ich denke, ich könnte es an das Dokument delegieren, aber das ist nur mehr Reisen und löst das Problem nicht. Was ist deine Lösung? – Amir

Antwort

-1

jQuery Ereignis unbinding und Elemente entfernen kann dong mit den folgenden Verfahren sein:

$.off()

$.remove()

+0

1) nicht ** e **; 2) Das ist nicht wirklich eine Antwort. Es ist ein Zeiger auf zwei Links im Web. Wenn Sie dies verbessern möchten, erklären Sie, wie das OP diese Funktionen verwenden würde, um sein Ziel zu erreichen. Beachten Sie, dass der in der Frage gezeigte Code bereits '.off()' und '.remove()' hat. –

-3

Die beste Methode, dies zu tun wäre alles entbinden des Event-Listener mit $ (selector) .off(); Methode und dann entfernen Sie das Element mit $ (Selektor) .remove();

Es würde alle Speicherlecks aufgrund der Event-Handler stoppen.

+0

Das OP hat bereits "off()" und "remove()" in ihrem Code; Das fügt nichts hinzu. –

1

Nicht sicher, dass dies immer noch relevant ist, aber aus dem Konsolenabbild nehme ich an, dass Sie Bootstrap-Tooltips verwenden, und sie scheinen den Verweis auf den DOM-Knoten zu halten. Ich schlage vor, Sie rufen die Zerstörungsmethode über die API

Verwandte Themen