2012-02-06 10 views
6

Pensavo di aver capito il potere concatenante di jQuery, ma ora sono un po 'confuso.simple jQuery Chaining insight

Usando l'esempio di dissolvenza un DIV, e quindi rimuovendolo:

  • Con jQuery logica concatenamento, che dovrebbe essere in grado di fare:

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

Invece io fare questo:

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

Perché è quello? Grazie!

risposta

11

Non è possibile chiamare .remove() subito perché l'operazione .fadeOut() è un'operazione asincrona che viene restituita immediatamente (dopo aver avviato l'animazione), ma continua ad essere eseguita tramite timer. Quando viene eseguito il .fadeOut() e viene eseguita l'operazione concatenata successiva, l'animazione è appena iniziata e non è stata completata. Se esegui lo .remove() con il concatenamento normale, lo rimuovi subito prima che l'animazione compia progressi.

Quindi, come hai scoperto, devi attendere che venga richiamata la chiamata di completamento per l'animazione e quindi puoi rimuoverla.

L'unica eccezione è rappresentata da ulteriori chiamate di animazione concatenate. Puoi concatenare le animazioni perché le animazioni sono un caso speciale che entra nella coda di animazione. Una volta che un'animazione è iniziata, le successive chiamate di animazione vedono che c'è già un'animazione in corso e entrano in una coda interna. Al termine della prima animazione, controlla la coda di animazione per vedere se ci sono più animazioni concatenate da avviare.

Quasi tutte le operazioni asincrone in javascript non sono bloccanti come questo. Ciò significa che la chiamata per avviarli è proprio questo: una chiamata per avviarli. La chiamata quindi ritorna immediatamente e il resto dell'operazione procede tramite timer o altri eventi e il successivo javascript continua l'esecuzione (inclusi altri metodi concatenati). Saprai solo quando l'operazione è effettivamente eseguita registrando per il callback di completamento.

Lo stesso vale per le operazioni di ajax, caricamento delle immagini, ecc ...

Si mi ha fatto pensare a come rendere il lavoro .remove() metodo attraverso la coda di animazione. in realtà si può fare che con la creazione di una nuova versione di remove() in questo modo:

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

Questa forma di rimuovere va nella coda di animazione ed eseguirà quando le animazioni incatenati prima che è fatto. Quindi, si potrebbe quindi utilizzare:

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

C'è un esempio di lavoro qui: http://jsfiddle.net/jfriend00/3Hg6G/

+1

Giusto per aggiungere a questo un po '. Le animazioni vengono aggiunte a una coda, le non animazioni no. 'remove' non è un'animazione, quindi avviene immediatamente. Attaccare qualcosa come 'fadeIn' dopo il' fadeOut' attenderà il completamento di 'fadeOut', perché viene messo in coda. Questo è spesso frainteso. –

+0

Ho difficoltà a capire questa decrizione di design in jQuery. Non imbroglia la maggior parte dei principianti (se non tutti)? – Leo

+0

@Leo: non è davvero una decisione di progettazione in jQuery. A causa del modo in cui funziona javascript, le operazioni che si eseguono per un lungo periodo di tempo con il browser in grado di rispondere agli eventi devono essere asincrone come questo (ad esempio, non bloccante). Quando sono asincroni, il motore javascript eseguirà solo le successive operazioni concatenate. Non c'è davvero un altro modo di usare il concatenamento e risolvere questo problema a meno che jQuery in qualche modo metta tutte le operazioni concatenate in una coda e questo potrebbe finire per essere ancora più complicato. Sì, fa finta i principianti. È solo qualcosa che deve essere imparato. – jfriend00

-1

Prova il modo:

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

Non funzionerà neanche. '.delay()' non è sincrono. È anche asincrono (passa attraverso la coda di animazione) proprio come il '.fadeOut()', quindi non ritarderà quando viene chiamato '.remove()'. – jfriend00

+0

Penso che troverete che questo non aiuta affatto perché [il metodo '.delay()'] (http://api.jquery.com/delay/) ritarda solo i successivi metodi di animazione. – nnnnnn

0

è possibile scrivere un plugin per rendere vi aspetta.

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

utilizzo:

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