2016-02-17 16 views
10

Ho creato una grande applicazione a pagina singola e recentemente ho iniziato a esplorare le perdite di memoria in JS. E penso di avere una perdita di memoria perché, poiché utilizzo la funzione Profiles (Snapshot) in Chrome, vedo che ho molti elementi DOM separati.Qual è il modo corretto per separare i listener di eventi e rimuovere elementi secondari nelle applicazioni di una sola pagina?

Ecco una visione semplificata della mia messa a punto:

<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> 

Quindi, se un utente fa clic sul pulsante A, per esempio, vorrei usare una chiamata AJAX per caricare il contenuto nella .ajaxHolder. Qualcosa di simile a questo:

//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> 

Ho anche due funzioni dentro la mia PRINCIPALE file di script. Uno sarebbe così:

//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); 
}); 

Fin qui tutto bene. Ma ora, con il contenuto caricato, ho anche questa funzione dentro la mia PRINCIPALE file script:

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

Così ora se l'utente preme il tasto B, per esempio, .ajaxHolder viene svuotato, ma tutti quegli eventi legati alla mia le caselle di controllo sembrano restare ferme, perché vengono visualizzate nel mio albero DOM distaccato.

Cosa mi manca qui? Come posso assicurarmi di non avere alcun elemento DOM staccato, in un'applicazione a singola pagina in esecuzione in questo modo?

BONUS DOMANDA: Ho un sacco di eventi legati in questo modo:

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

Vale a dire, tutto è sempre attaccato al mio .ajaxHolder, perché devo utilizzare la delega evento dal .ajaxHolder sarà sempre esistono - mentre altri elementi che vengono caricati non sempre esisteranno, quindi non posso semplicemente fare $(button).on('click')..., ecc.

Quindi, questo è anche il modo corretto di fare questo? C'è un limite a quante cose posso allegare a questo .ajaxHolder o non ci sono problemi con questo?

MODIFICA: ecco un'immagine della mia console, se questo aiuta affatto.

enter image description here

+2

rimuovere l'elemento con un metodo jQuery è più che sufficiente per rimuovere tutti i dati associati, purché i dati siano stati associati usando jQuery. Non è necessario separare manualmente gli eventi. –

+0

Si può fare delegazione su ajaxHolder tutto ciò che si desidera, tuttavia, trovo che possa facilmente sfuggire di mano mano mano che il progetto cresce. Può anche iniziare a ostacolare le prestazioni se ci sono molti gestori di eventi associati allo stesso tipo, tuttavia è probabile che si verifichino problemi di manutenibilità molto prima che si inizi ad avere un problema di prestazioni. –

+0

@KevinB Quindi, perché vengono visualizzati gli elementi dom distaccati? Qualche altra causa che manterrebbe un riferimento agli articoli, che sono stati rimossi? E, per la seconda parte, quale altra opzione ho, oltre a delegarla all'ajaxHolder ... Credo che potrei delegarla al documento, ma questo è solo più viaggio e non risolve il problema. Qual è la tua soluzione? – Amir

risposta

-1

jQuery evento non vincolante e la rimozione degli elementi può essere dong con i seguenti metodi:

$.off()

$.remove()

+0

1) don ** e **; 2) Questa non è davvero una risposta. È un puntatore a due collegamenti sul web. Se vuoi migliorare questo, spiega come l'OP userebbe quelle funzioni per raggiungere il loro obiettivo. Si noti che il codice mostrato nella domanda ha già entrambi ".off()" e ".remove()". –

-3

Il metodo migliore per farlo sarebbe quello di separare tutto il ascoltatori di eventi usando $ (selector) .off(); metodo e quindi rimuovere l'elemento usando $ (selector) .remove();

Arresterebbe tutte le perdite di memoria che si verificano a causa dei gestori di eventi.

+0

L'OP ha già sia 'off()' che 'remove()' nel proprio codice; questo non aggiunge nulla. –

1

Non sono sicuro che questo sia ancora rilevante, ma dall'immagine della console che raccolgo si stanno utilizzando le descrizioni dei comandi di bootstrap e sembrano tenere il riferimento al nodo DOM. Suggerisco di chiamare il metodo destroy tramite API