2012-02-06 31 views
6

Tôi nghĩ rằng tôi hiểu sức mạnh chuỗi của jQuery, nhưng bây giờ tôi là một chút bối rối.đơn giản jQuery Chaining cái nhìn sâu sắc

Sử dụng ví dụ của fading ra một DIV, và sau đó loại bỏ nó:

  • By jQuery chaining được kết logic, tôi sẽ có thể làm:

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

Nhưng thay vào đó tôi phải làm điều này:

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

Tại sao lại như vậy? Cảm ơn!

Trả lời

11

Bạn không thể gọi .remove() ngay lập tức vì thao tác .fadeOut() là một hoạt động không đồng bộ trả về ngay lập tức (sau khi khởi động hoạt ảnh), nhưng vẫn tiếp tục thực hiện qua bộ hẹn giờ. Khi trả về .fadeOut() và thao tác chuỗi tiếp theo thực hiện, hoạt ảnh chỉ mới bắt đầu - nó chưa hoàn thành. Nếu bạn làm .remove() với chuỗi bình thường, bạn xóa nó ngay lập tức trước khi hoạt ảnh thực hiện bất kỳ tiến bộ nào.

Vì vậy, như bạn đã phát hiện, bạn phải chờ cho đến khi hoàn thành gọi lại được gọi là cho các hình ảnh động và sau đó bạn có thể loại bỏ nó.

Một ngoại lệ cho điều này là các cuộc gọi hoạt ảnh có chuỗi bổ sung. Bạn có thể chuỗi hoạt ảnh vì hoạt ảnh là trường hợp đặc biệt đi vào hàng đợi hoạt ảnh. Khi hoạt ảnh đã bắt đầu, các cuộc gọi hoạt ảnh tiếp theo sẽ thấy rằng đã có một hoạt ảnh đang diễn ra và chúng sẽ đi vào hàng đợi nội bộ. Khi hoạt ảnh đầu tiên kết thúc, nó sẽ kiểm tra hàng đợi hoạt ảnh để xem liệu có nhiều hoạt ảnh bắt đầu hay không.

Gần như tất cả các hoạt động không đồng bộ trong javascript đều không bị chặn như thế này. Điều đó có nghĩa là các cuộc gọi để bắt đầu họ chỉ là - một cuộc gọi để bắt đầu chúng. Cuộc gọi đó sau đó sẽ trở lại ngay lập tức và phần còn lại của hoạt động được thực hiện thông qua tính giờ hoặc các sự kiện khác và javascript tiếp theo tiếp tục thực hiện (bao gồm cả các phương thức xích khác). Bạn sẽ chỉ biết khi nào hoạt động thực sự được thực hiện bằng cách đăng ký gọi lại hoàn thành.

Điều này cũng đúng cho các hoạt động ajax, tải hình ảnh, vv ...

Bạn đã cho tôi suy nghĩ về làm thế nào để làm cho công việc .remove() phương pháp thông qua hàng đợi hình ảnh động. Trên thực tế, bạn có thể thực hiện điều đó bằng cách tạo phiên bản xóa mới() như sau:

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

Hình thức xóa này nằm trong hàng hoạt ảnh và sẽ thực hiện khi hoạt ảnh được ghép trước khi hoàn thành. Vì vậy, sau đó bạn có thể sử dụng:

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

Có một ví dụ làm việc ở đây: http://jsfiddle.net/jfriend00/3Hg6G/

+1

Chỉ cần thêm vào đó một chút. Ảnh động được thêm vào hàng đợi, không phải hình động. 'remove' không phải là hoạt ảnh nên nó diễn ra ngay lập tức. Gắn bó một cái gì đó như 'fadeIn' sau khi' fadeOut' sẽ đợi 'fadeOut' hoàn thành, bởi vì nó được xếp hàng đợi. Điều này thường bị hiểu lầm. –

+0

Tôi có một thời gian khó hiểu sự phân tích thiết kế này trong jQuery. Nó không đánh lừa hầu hết người mới bắt đầu (nếu không phải tất cả)? – Leo

+0

@Leo - nó không thực sự là một quyết định thiết kế trong jQuery. Do cách javascript hoạt động, các hoạt động thực thi trong một khoảng thời gian dài với trình duyệt có thể phản hồi các sự kiện phải không đồng bộ như thế này (ví dụ: không chặn). Khi chúng không đồng bộ, công cụ javascript sẽ chỉ thực hiện các hoạt động chuỗi tiếp theo. Có thực sự không phải là một cách khác để sử dụng chuỗi và giải quyết vấn đề này trừ khi jQuery bằng cách nào đó đặt tất cả các hoạt động chuỗi vào một hàng đợi và có thể kết thúc thậm chí còn phức tạp hơn. Có, nó đánh lừa người mới bắt đầu. Nó chỉ là cái gì đó phải được học. – jfriend00

-1

Thử cách này:

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

Điều đó sẽ không hoạt động. '.delay()' không đồng bộ. Nó cũng không đồng bộ (đi qua hàng đợi hoạt hình) giống như '.fadeOut()' do đó nó sẽ không trì hoãn khi '.remove()' thực sự được gọi. – jfriend00

+0

Tôi nghĩ bạn sẽ thấy rằng điều này không giúp gì cả vì [phương thức '.delay()'] (http://api.jquery.com/delay/) chỉ trì hoãn các phương thức hoạt ảnh tiếp theo. – nnnnnn

0

Bạn có thể viết một plugin để làm cho nó chờ đợi cho bạn.

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

sử dụng:

$(this).parent().fadeOut(500).q('remove'); 
Các vấn đề liên quan