2012-02-06 73 views
6

我想我明白的jQuery的鏈接能力,但現在我有點困惑。簡單的jQuery鏈的洞察力

使用淡出DIV,然後除去它的例子:

  • 的jQuery鏈的邏輯,我應該能夠做到:

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

而是我必須這樣做:

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

這是爲什麼?謝謝!

回答

11

您不能立即致電.remove(),因爲.fadeOut()操作是立即返回(在它剛開始動畫之後)的異步操作,而是通過定時器繼續執行。當.fadeOut()返回並執行下一個鏈接操作時,動畫纔剛剛開始 - 尚未完成。如果您使用正常鏈接執行.remove(),則在動畫取得進展之前立即將其刪除。

因此,當你發現,你必須等待,直到完成回調被稱爲爲動畫,然後你可以將其刪除。

一個例外,這是額外的鏈式動畫調用。您可以鏈接動畫,因爲動畫是進入動畫隊列的特例。一旦動畫開始,隨後的動畫調用就會看到已經有一個動畫正在進行,並進入內部隊列。當第一個動畫完成時,它會檢查動畫隊列,看看是否有更多的鏈接動畫開始。

幾乎所有異步操作的JavaScript是不可阻擋這樣的。這意味着啓動它們的呼叫就是這樣 - 啓動它們的呼叫。然後該調用立即返回,其餘操作通過定時器或其他事件繼續進行,隨後的JavaScript繼續執行(包括其他鏈式方法)。您只會通過註冊完成回調來了解操作何時完成。

這同樣適用於Ajax操作,圖像的加載,等真的......

你讓我開始思考如何通過動畫隊列作出.remove()方法的工作。人們可以在事實上做到這一點通過創建刪除的新版本()是這樣的:

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

刪除的這種形式進入動畫隊列中,當它完成之前的動畫鏈接將被執行。所以,你可以再使用:

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

這裏有一個工作示例:http://jsfiddle.net/jfriend00/3Hg6G/

+1

只是爲了添加到咯。動畫被添加到隊列中,而非動畫則不會。 '刪除'不是一個動畫,所以它立即發生。在'fadeOut'之後插入'fadeIn'等待'fadeOut'完成,因爲它被排隊。這經常被誤解。 – 2012-02-06 03:54:14

+0

我很難理解jQuery中的這種設計決策。它不是愚弄大多數初學者(如果不是全部)? – Leo 2012-02-06 03:54:25

+0

@Leo - 這不是jQuery中的設計決定。由於JavaScript的工作方式,瀏覽器能夠響應事件很長一段時間執行的操作必須像這樣異步(例如非阻塞)。當它們是異步時,JavaScript引擎將執行下一個鏈接操作。除非jQuery以某種方式將所有鏈接操作放入隊列中,並且最終會變得更加複雜,否則實際上沒有其他方法可以使用鏈接並解決此問題。是的,它確實愚弄初學者。這只是必須學習的東西。 – jfriend00 2012-02-06 04:00:28

-1

嘗試的方式:

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

這也行不通。 '.delay()'不是同步的。它也是異步的(通過動畫隊列),就像'.fadeOut()'一樣,所以當實際調用'.remove()'時它不會延遲。 – jfriend00 2012-02-06 05:29:39

+0

我想你會發現這並沒有什麼幫助,因爲[.delay()'方法](http://api.jquery.com/delay/)只會延遲後續的動畫方法。 – nnnnnn 2012-02-06 05:30:22

0

您可以編寫一個插件,使之等你。

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

用法:

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