2010-10-28 9 views
12

¿Alguien sabe cómo saber si un objeto jQuery almacenado en caché se ha quedado obsoleto, p. ya no está en el DOM? Por ejemplo:comprueba si el objeto jquery almacenado en caché todavía está en DOM

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

// .. and then later 

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

que he encontrado recientemente la situación en la que $ cached_elem se retira del DOM debido a algún otro evento. Así que lo que me gustaría hacer:

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

Antes de que nadie ofrece, ya he empleado este, que es un análogo justo por lo que estoy tratando de hacer:

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

Sin embargo, esto es no es realmente lo mismo y podría fallar en algunos casos.

Entonces, ¿alguien puede pensar en una forma sencilla de verificar directamente si un objeto jQuery almacenado en caché está "obsoleto"? I puede ser obligado a escribir un plugin si no ...

Respuesta

21

if($elem.closest('body').length > 0) parece que podría hacer el truco.

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

Editar: actualizado en respuesta al comentario de Yi Jiang modo que le proporcione correctamente si su elemento padre se retira

Edición 2: Actualizado en respuesta a lonesomeday de comentario - ha cambiado parents() a 'más cercano() `para la mejora del rendimiento

+1

Pero, ¿qué sucede si, por ejemplo, elimino el * padre * del elemento? Lo que necesita hacer, creo, es detectar si 'body' sigue siendo uno de los elementos principales del elemento en cuestión, como este: http://jsfiddle.net/D9L8M/1/ –

+0

Buen punto - código actualizado para reflejar que –

+0

'$ elem.closest ('body'). Length' debe ser un poco más rápido. También puede seleccionar '' html' 'si quita, por ejemplo, un elemento 'link' del' head'. – lonesomeday

0

Si el selector no ha cambiado, simplemente reinicializarla:

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

Si se quiere evitar la duplicación de la cadena de selección, utilice la propiedad selector del objeto jQuery originales:

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í, por supuesto. Pero no estamos usando jQuery así. Queremos definir el selector una vez, y luego no preocuparnos por el método del selector original por una serie de buenas razones. Los ejemplos incluyen la necesidad de refactorizar el mecanismo de Mecha de caché o la capacidad de introducir errores cuando el selector está duplicado en dos o más lugares. Mejor si pudiéramos decir si $ cached_elem.isStillInDOM()) o si ($ cached_elem.isStale()) {... –

+0

¿Por qué no simplemente usar una variable para el selector? De esta forma, si necesita cambiarlo en el futuro, no hay riesgo de olvidar cambiar una ocurrencia de él.Incluso podría usar la propiedad selector del objeto jQuery original: '$ cached_elem = $ ($ cached_elem.selector);' –

+0

¡Ajá! Esa es la propiedad que estoy buscando, creo. Entonces, ¿funcionaría esto: if ($ ($ cached_elem) .selector) .length <1) {....}? –

0

En un caso ligeramente variante, se puede comparar directamente el elemento DOM nativo envuelto por el objeto jQuery $cached_elem.

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

Además de comprobar si el $cached_elem se encuentra todavía en DOM, éste puede decir que si sigue siendo el elemento DOM original, en lugar de una re-creado uno con mismos atributos después de cierta actualización de la página/parcial.

5

El método nativo document.contains() debe ser más rápido que jQuery para determinar si existe un elemento jQuery en caché en el DOM.

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

I benchmarked y confirm document.contains es mucho más rápido. $ elem.closest ('body') .length> 0 toma aproximadamente 1/81,000s, mientras que document.contains() toma aproximadamente 1/1,300,000s. Así que document.contains es alrededor de 16 veces más rápido. div_el = document.createElement ('div'); document.contains (div_el); // devuelve falso. ¡Bueno! document.body.appendChild (div_el); document.contains (div_el) // devuelve verdadero. Quite el div y contains() nuevamente informa falso. Esto también funciona cuando se agrega y elimina en la cabeza y tiene un buen soporte en los navegadores modernos. ¡Excelente! –

+0

'document.contains()' no funciona en Internet Explorer. Una solución para IE es usar 'document.body.contains()'. Sin embargo, tenga en cuenta que si '$ cached_elem' es el' document' en sí, 'document.body.contains()' devolverá false. Terminé usando algo como 'if ($ cached_elem [0] === document || document.body.contains ($ cached_elem [0])) {...}'. – Robert

Cuestiones relacionadas