2009-10-12 33 views
48

Tôi rất tò mò nếu có thể tạo sự kiện tùy chỉnh trong jQuery không bị ràng buộc với thành phần DOM.Sự kiện tùy chỉnh trong jQuery không bị ràng buộc với phần tử DOM?

Tôi rất thích jQuery với YUI nhưng có một điều trong YUI mà tôi thích, đó là tạo sự kiện tùy chỉnh và có thể đăng ký với họ sau này.

Ví dụ, điều này tạo ra một sự kiện được liên kết với một biến, không để một phần tử DOM:

var myevent = new YAHOO.util.CustomEvent("mycustomevent"); 

Tất cả các ví dụ và tài liệu hướng dẫn Tôi đã được đọc cho jQuery đòi hỏi một cái gì đó như:

$('body').bind('mycustomevent', function(){ 
    //do stuff 
}); 
+1

Tôi đoán jquery sẽ không hiểu sự kiện 'mycustomevent' và YUI nào cả. Tuy nhiên bạn có thể thử sử dụng con trỏ: 'bind (myevent,' .. – jantimon

+0

tôi nghĩ rằng, tương tự như Django, có một số thực hành tốt nhất trong JQuery. Lúc đầu, các trình cắm thêm. Bạn có thể tạo sự kiện tùy chỉnh của mình như một bên ngoài lớp, là một plug-in cho JQuery, và bạn chỉ có thể ràng buộc sự kiện của bạn với phần tử của bạn bằng cách sử dụng bất kỳ bộ chọn, chẳng hạn như $ ("# myDiv"). myPlugin ("thực hiện rất nhiều thứ") có một số cách làm điều đó, nhưng bạn nên thừa nhận đầu tiên chính xác những gì bạn cần. bạn có thể xây dựng một chút? tôi có thể cố gắng để cung cấp cho bạn bình luận chính xác hơn) thx – 0100110010101

+0

Hi! Họ chấp nhận câu trả lời là không chính xác (hoặc không chính xác * nữa *). Có lẽ bạn có thể thay đổi câu trả lời được chấp nhận cho tôi? – sbichenko

Trả lời

43

Bạn có thể kích hoạt sự kiện tùy biến toàn cục như thế này trong jQuery:

jQuery.event.trigger('mycustomevent', [arg1, arg2, arg3]); 

Những điều này sẽ kích hoạt cho bất kỳ phần tử nào.

Vì jQuery được xây dựng xung quanh các đối tượng DOM, bạn phải liên kết sự kiện của mình với đối tượng DOM. Bạn có lẽ có thể tìm thấy một số cách để ràng buộc các sự kiện mà không có một yếu tố quá (bạn đã làm), nhưng đó không phải là một phương pháp được hỗ trợ.

Như bạn đã viết trong câu trả lời của riêng bạn, bạn có thể liên kết sự kiện của bạn cho một đối tượng DOM toàn cầu nếu bạn không muốn để ràng buộc nó vào một yếu tố trang cá nhân:

$(document).bind('mycustomevent', function (e, arg1, arg2, arg3) { /* ... */ }); 
+7

có vẻ như jQuery hỗ trợ điều này ngay bây giờ: http://bugs.jquery.com/ticket/7818#comment:26, http://forum.jquery.com/topic/triggering-custom-events-on-js-objects. Cách giải quyết 'triggerHandler' được đề cập trong liên kết cũng được sửa trong số 7930. – hyperslug

+2

Yep, jQuery thực sự hỗ trợ điều này ngay bây giờ (xem câu trả lời của tôi: http://stackoverflow.com/a/26062543/710356) – sbichenko

6

Đối với độc giả trong tương lai, khá của nó đơn giản để làm điều này. Tôi đã nghiên cứu thêm sau khi đăng câu hỏi của mình. Rất tiếc, không có người bình luận nào khác là chính xác.

Để ràng buộc một sự kiện tùy chỉnh:

$().bind('mycustomevent', function(){ 
    //code here 
}); 

Ngoài ra, bạn có thể xây dựng dữ liệu vào đối tượng sự kiện đó là sau truy cập:

$({mydata:'testdata'}).bind('mycustomevent',function(){ 
    //code here 
}); 
+17

Bạn nên biết rằng với '$()' bạn vẫn còn ràng buộc nó với một đối tượng DOM (' $() 'cũng giống như làm' $ (tài liệu) '). '$ ({})' hoạt động, nhưng bạn nên biết rằng nó hoạt động vì jQuery không bao giờ kiểm tra xem đó là một đối tượng DOM. Nó vẫn kết thúc tốt đẹp nó với một đối tượng jQuery có các phương thức như 'append (...)' sẽ dừng tập lệnh của bạn nếu được gọi. Ngoài ra, hành vi để gói các đối tượng không phải DOM là không xác định và có thể thay đổi trong tương lai. Vì vậy, tôi vẫn đứng theo quan điểm của tôi trong câu trả lời của tôi, và khuyên bạn nên liên kết nó với '$ (document)' chứ không phải là một đối tượng JavaScript. – Blixt

3

Bạn vẫn có thể tùy ý kích hoạt và phản ứng với các sự kiện bằng cách sử dụng jQuery, ngay cả khi bạn không biết phần tử nào để đính kèm chúng vào. Chỉ cần tạo phần tử "người nhận" trong tài liệu của bạn, mà bạn có thể ràng buộc tất cả các sự kiện tùy chỉnh của mình. Điều này cho phép bạn quản lý logic xử lý sự kiện của mình ở một nơi, cho tất cả các sự kiện không thuộc phần tử cụ thể của bạn.

$(document).ready(function() { 

    $(body).append('<div id="receiver">'); 

    $("#receiver").bind("foo_event", function() { 
    // decide what to do now that foo_event has been triggered. 
    }); 

    $("#some_element").click(function() { 
    $("#receiver").trigger("foo_event"); 
    }); 

}); 
+0

Tôi nghĩ đó là một ý tưởng tồi. Nếu bạn thực sự muốn một số phần tử gắn các sự kiện vào, tại sao không sử dụng '$ ('body')' hoặc '$ (document)'? – Blixt

+5

Nó chỉ là một quy ước hoạt động.Tôi thích nó hơn bằng cách sử dụng tài liệu hoặc cơ thể bởi vì nó hoạt động giống như một thanh toán bù trừ vô trùng cho các sự kiện - tôi biết tất cả mọi thứ trong đó, và ít có khả năng xấu không mong muốn xảy ra do tai nạn. Bạn có thể giải thích tại sao bạn nghĩ đó là một ý tưởng tồi? –

5

Ràng buộc với các thành phần không có phần đã được xóa trong jQuery 1.4.4.

+0

Điều đó có nghĩa là gì? – ppumkin

+0

Có lẽ, anh ấy có nghĩa là các đối tượng JavaScript đơn giản? –

+0

Bạn đang đề cập đến [this] (http://stackoverflow.com/a/26062543/4967497) trả lời? – JojOatXGME

3

jQuery Callbacks cung cấp cách đơn giản để triển khai hệ thống phụ-pub độc lập với DOM.

Gần cuối trang được liên kết là mã mẫu cho biết cách thực hiện điều đó.

1

[EDIT]

Dưới đây là một tầng lớp lao động có sử dụng các khái niệm văn bản dưới đây:

https://github.com/stratboy/image-preloader

Nó chỉ là một trình nạp trước hình ảnh tuần tự. Bạn có thể đăng ký một loạt các sự kiện. Hãy xem.

[/ EDIT]

Cũ bài:

Dưới đây là một ví dụ khác barebones với callbacks như đề xuất bởi Himanshu P.

Tôi đang xây dựng một lớp học và tôi đến từ Mootools, nơi mà mọi thứ như Các lớp và các sự kiện tùy chỉnh được triển khai trực tiếp trong các lớp (do đó không ràng buộc với các phần tử DOM) là hoàn toàn tự nhiên. Vì vậy, tôi đã thử một cách giải quyết khác và chia sẻ bên dưới.

var step_slider; 

    //sandbox 
    ;(function($) { 

//constructor 
var StepSlider = function(slider_mask_selector,options) { 

    //this.onStep = $.Event('step'); 
    this.options = null; 
    this.onstep = $.Callbacks(); 

    this.init(); 
}//end constructor 

StepSlider.prototype = { 

    init:function(){ 
     this.set_events(); 
    },//end init 

    set_events:function(){ 

     if(this.options){ 
      if(this.options.onstep){ 
       this.subscribe('step',options.onstep); 
      } 
     } 

    },//set_events 

    subscribe:function(event,action){ 
     this['on'+event].add(action); 
    }, 

    fire_onstep:function(){ 
     this.onstep.fire({ data1:'ok' }); 
    } 

}//end prototype/class 

//-------------------- 

$(document).ready(function() { 

    step_slider = new StepSlider('selector'); 

    //for example, say that you have a div#next-button, you can then do this: 
    $('#next-button').click(function(){ 
     step_slider.fire_onstep(); 
    }); 

});//end domready 


})(jQuery); 
+0

đó không phải là một lớp học. –

+0

@low_rents: có thể không dành cho ES6, nhưng miễn là bạn có thể khởi tạo các đối tượng từ nó (ClassName mới), đó là một lớp. Hoặc, đó là một cách (cũ) javascript để làm một cái gì đó giống như một lớp học, hãy nhớ rằng javascript không có cú pháp/đường dẫn/thừa kế thực sự như ActionScript 3 và ES6. Có lẽ một trong những triển khai js oop tốt nhất trước ES6 là cách coffescript tạo ra các lớp js (chỉ cần tạo một và xem mã được biên dịch), nhưng ở trên nó là một thực hiện đơn giản hơn và đó là một thỏa hiệp tốt để có được khép kín, được tổ chức tốt đối tượng được khởi tạo vô hạn lần. – Stratboy

39

Theo a comment by John Resig, sự kiện ràng buộc các đối tượng tùy chỉnh thông qua jQuery được hỗ trợ:

Không có lý do cụ thể tại sao nó không phải tài liệu (trừ rằng nó khá phi truyền thống đối với hầu hết người dùng) - nhưng có, chúng tôi hỗ trợ nó và có các bài kiểm tra đơn vị cho nó.

Vì vậy, công trình này:

var a = {foo: 'bar'}; 
$(a).on('baz', function() {console.log('hello')}); 
$(a).triggerHandler('baz'); 
>>> 'hello' 

Hầu hết người dùng sẽ cần triggerHandler(), không trigger(). Nếu .trigger("eventName") được sử dụng, nó sẽ tìm kiếm một thuộc tính "eventName" trên đối tượng và cố gắng thực hiện nó sau khi bất kỳ trình xử lý jQuery đính kèm nào được thực hiện (Source).

EDIT (2017/02/28):

Sau khi sử dụng mô hình này trong khoảng 2 năm trong một codebase lớn, tôi có thể chứng thực rằng đây là một ý tưởng tồi. Các sự kiện tùy chỉnh này dẫn đến luồng dữ liệu không thể hiểu được. Ưu tiên gọi lại các cuộc gọi lại.

+9

Đây phải là câu trả lời được chấp nhận – MatteoSp

+1

Câu hỏi ngớ ngẩn: Câu hỏi có lý do tại sao nó không được ghi chép? Không nên sử dụng nó? Nó có thể được gỡ bỏ/sửa đổi trong một phiên bản mới hơn? Tôi tự hỏi nếu tôi nên sử dụng nó trong lợi của libs phụ pub khác như [EvenEmitter] (https://github.com/Olical/EventEmitter). – robsch

Các vấn đề liên quan