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.
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. –
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. –
@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