2012-02-06 32 views
6

Pensé que entendía el poder de jQuery, pero ahora estoy un poco confundido.simple jQuery Chaining insight

Utilizando el ejemplo de desvanecimiento un DIV, y luego se retire:

  • Por jQuery lógica de encadenamiento, yo debería ser capaz de hacer:

    $(this).parent().fadeOut(500).remove(); 
    

Pero en lugar de eso tiene que hacer esto:

$(this).parent().fadeOut(500,function() { $(this).remove(); }); 

¿Por qué es eso? ¡Gracias!

Respuesta

11

No se puede llamar al .remove() de forma inmediata porque la operación .fadeOut() es una operación asincrónica que vuelve inmediatamente (después de que acaba de iniciar la animación), pero continúa ejecutándose a través de temporizadores. Cuando regresa el .fadeOut() y se ejecuta la siguiente operación encadenada, la animación acaba de comenzar, no se ha completado. Si haces el .remove() con un encadenamiento normal, lo quitas inmediatamente antes de que la animación avance.

Por lo tanto, como ha descubierto, tiene que esperar hasta que se llame a la devolución completa para la animación y luego puede eliminarla.

La única excepción a esto son las llamadas de animación encadenadas adicionales. Puede encadenar animaciones porque las animaciones son un caso especial que entra en la cola de animación. Una vez que se inicia una animación, las llamadas de animación posteriores ven que ya hay una animación en progreso y entran en una cola interna. Cuando finaliza la primera animación, comprueba la cola de animación para ver si hay más animaciones encadenadas para comenzar.

Casi todas las operaciones asíncronas en javascript no son bloqueantes como esta. Eso significa que la llamada para iniciarlos es solo eso, una llamada para iniciarlos. Esa llamada luego regresa de inmediato y el resto de la operación se realiza a través de temporizadores u otros eventos y el siguiente javascript continúa ejecutándose (incluidos otros métodos encadenados). Solo sabrá cuando la operación se haya realizado registrándose para la devolución de llamada de finalización.

Lo mismo es cierto para las operaciones de ajax, carga de imágenes, etc ...

Usted me hizo pensar acerca de cómo hacer el trabajo .remove() método a través de la cola de la animación. de hecho, uno puede hacerlo mediante la creación de una nueva versión de remove() así:

$.fn.fxRemove = function() { 
    this.queue(function(next) { 
     $(this).remove(); 
     next(); 
    }); 
    return(this); 
} 

Esta forma de quitar va en la cola de la animación y se ejecutará cuando las animaciones encadenados antes de que se llevan a cabo. Por lo tanto, se puede entonces utilizar:

$(this).parent().fadeOut(500).fxRemove(); 

Hay un ejemplo de trabajo aquí: http://jsfiddle.net/jfriend00/3Hg6G/

+1

sólo para añadir a eso un poco. Las animaciones se agregan a una cola, las no animaciones no. 'eliminar' no es una animación, por lo que sucede de inmediato. Pegar algo como 'fadeIn' después de' fadeOut' esperaría a que 'fadeOut' se complete, porque se pone en cola. Esto a menudo es malentendido. –

+0

Me es difícil entender esta decisión de diseño en jQuery. ¿No engaña a la mayoría de los principiantes (si no todos)? – Leo

+0

@Leo: en realidad, no es una decisión de diseño en jQuery. Debido a la forma en que funciona JavaScript, las operaciones que se ejecutan durante un largo período de tiempo con el navegador capaz de responder a los eventos tienen que ser asíncronas como esta (por ejemplo, sin bloqueo). Cuando son asíncronos, el motor de JavaScript simplemente ejecutará las siguientes operaciones encadenadas. Realmente no hay otra manera de utilizar el encadenamiento y resolver este problema a menos que jQuery de alguna manera ponga todas las operaciones encadenadas en una cola y eso podría terminar siendo aún más complicado. Sí, engaña a los principiantes. Es solo algo que debe ser aprendido. – jfriend00

-1

Trate de la forma:

$(this).parent().fadeOut().delay(500).remove(); 
+0

Eso tampoco funcionará. El '.delay()' no es sincrónico. También es asíncrono (pasa por la cola de animación) al igual que '.fadeOut()' por lo que no se demorará cuando se llame realmente a '.remove() '. – jfriend00

+0

Creo que encontrará que esto no ayuda en nada porque [el método '.delay()'] (http://api.jquery.com/delay/) solo retrasa los métodos de animación posteriores. – nnnnnn

0

puede escribir un plugin para hacer que esperar para usted.

DEMO

$.fn.q = function(fn) { 
    var that = this, arg = Array.prototype.slice.call(arguments, 1); 

    return this.queue(function(next) { 
     that[fn].apply(that, arg); 
     next(); 
    }); 
}; 

uso:

$(this).parent().fadeOut(500).q('remove'); 
Cuestiones relacionadas