2010-10-28 10 views
12

Qualcuno sa come stabilire se un oggetto jQuery memorizzato nella cache è diventato obsoleto, ad es. non è più nel DOM? Per esempio:controlla se l'oggetto jQuery memorizzato nella cache è ancora in DOM

var $cached_elem = $('.the_button'); 

// .. and then later 

$cached_elem.text('updating...'); 

ho recentemente incontrato la situazione in cui il $ cached_elem viene rimosso dal DOM a causa di qualche altro evento. Quindi quello che vorrei fare:

if ($cache_elem.isStillInDOM()){ 
    // now do time consuming stuff with $cached_elem in DOM 
} 

Prima che qualcuno propone, ho già impiegato questo, che è un analogo equo per quello che sto cercando di fare:

if ($cached_elem.is(':visible') === true){ ... } 

Tuttavia, questo è non proprio la stessa cosa e potrebbe fallire in alcuni casi.

Quindi qualcuno può pensare a un modo semplice per controllare direttamente se un oggetto jQuery memorizzato nella cache è "obsoleto"? I può essere costretto a scrivere un plugin, se non ...

risposta

21

if($elem.closest('body').length > 0) sembra che potrebbe fare il trucco.

$(function() { 
 
    var $button = $(".the_button"); 
 
    alert (isStale($button)); 
 
    $button.remove(); 
 
    alert (isStale($button)); 
 
}); 
 
    
 
function isStale($elem) 
 
{ 
 
    return $elem.closest("body").length > 0; 
 
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div> 
 
    <span class="the_button">Hello World</span> 
 
</div>

Edit: aggiornata in risposta al commento di Yi Jiang in modo che restituisca correttamente se suo elemento genitore viene rimosso

Edit 2: aggiornati in risposta alla lonesomeday di commento - modificato parents() a "closest"() per il miglioramento delle prestazioni

+1

Ma cosa succede se, per esempio, rimuovo * parent * dell'elemento? Quello che devi fare penso sia quello di rilevare se 'body' è ancora uno dei genitori dell'elemento in questione, come questo: http://jsfiddle.net/D9L8M/1/ –

+0

Good point - codice aggiornato per riflettere che –

+0

'$ elem.closest ('body'). Length' dovrebbe essere un po 'più veloce. Puoi anche selezionare su "html" se stai rimuovendo, ad esempio, un elemento 'link' dal' head'. – lonesomeday

0

Se il selettore non è cambiata, basta reinizializzare esso:

var $cached_elem = $('.the_button'); 
// code that might remove some elements of $cached_elem 
$cached_elem = $('.the_button'); 

Se si vuole evitare di duplicare la stringa di selezione, utilizzare la proprietà selector dell'oggetto jQuery originale:

var $cached_elem = $('.the_button'); 
// code that might remove some elements of $cached_elem 
$cached_elem = $($cached_elem.selector); 
if ($cached_elem.length) { 
    // element still exists 
} 
+1

Sì, certo. Ma non stiamo usando jQuery in questo modo. Vogliamo definire il selettore una volta, e quindi non preoccuparti del metodo di selezione originale per una serie di buoni motivi. Gli esempi includono la necessità di rifattorizzare il meccanismo del meccanismo di memorizzazione nella cache o la capacità di introdurre errori quando il selettore è duplicato in due o più punti. Meglio se potessimo solo dire se $ cached_elem.isStillInDOM()) o se ($ cached_elem.isStale()) {... –

+0

Perché non usare semplicemente una variabile per il selettore, allora? In questo modo, se hai bisogno di cambiarlo in futuro, non c'è il rischio di dimenticare di cambiarne una.Si potrebbe anche usare la proprietà selector dell'oggetto jQuery originale: '$ cached_elem = $ ($ cached_elem.selector);' –

+0

Aha! Questa è la proprietà che sto cercando, penso. Quindi questo dovrebbe funzionare: if ($ ($ cache_elem) .selector) .length <1) {....}? –

0

In un caso leggermente variante, è possibile confrontare direttamente l'elemento DOM nativo racchiuso dall'oggetto jQuery $cached_elem.

$cached_elem[0] === $($cached_elem.selector)[0] 

Oltre a verificare se il $cached_elem è ancora in DOM, questo può dire se è ancora l'elemento DOM originale, piuttosto che una ri-creato uno con stessi attributi dopo un certo refresh della pagina/parziale.

5

Il metodo nativo document.contains() deve essere più veloce di jQuery per determinare se esiste un elemento jQuery memorizzato nella cache nel DOM.

if (document.contains($cached_elem[0])) { 
    // Element is still in the DOM 
} 
+2

Ho benchmark e confermato document.contains è molto più veloce. $ elem.closest ('body') .length> 0 impiega circa 1/81.000, mentre document.contains() richiede circa 1/1.300.000. Quindi document.contains è circa 16 volte più veloce. div_el = document.createElement ('div'); document.contains (div_el); // restituisce false. Buona! document.body.appendChild (div_el); document.contains (div_el) // restituisce true. Rimuovere il div e contiene() di nuovo segnala false. Funziona anche quando aggiunto e cancellato in testa e ha un buon supporto nei browser moderni. Eccellente! –

+0

'document.contains()' non funziona in Internet Explorer. Una soluzione alternativa per IE è utilizzare 'document.body.contains()'. Tuttavia, si noti che se '$ cached_elem' è il' documento' stesso, 'document.body.contains()' restituirà false. Ho finito per usare qualcosa come 'if ($ cached_elem [0] === document || document.body.contains ($ cached_elem [0])) {...}'. – Robert

Problemi correlati