2011-11-11 32 views
13

Tôi đang triển khai mẫu mô-đun và muốn biết cách tốt nhất/ưa thích để xác định và đăng ký trình xử lý sự kiện/trình xử lý sự kiện. Các công trình sau đây, nhưng có lẽ có một/cách đơn giản hơn ...Sự kiện và mô hình mẫu mô-đun Javascript

var MODULE = function() { 

    // private 
    var _field1; 
    var _field2; 

    function localFunc(p) { 
     alert('localFunc'); 
    } 

    // public 
    return { 
     // properties 
     prop1: _field1, 

     // events 
     myEvent1Handler: {}, 
     myEvent1: function() {myEvent1Handler();}, 
     myEvent2Handler: {}, 
     myEvent2: function() {myEvent2Handler();}, 

     addListener: function (event,func) { 
      if (event == "myEvent1") 
       myEvent1Handler = func; 

      if (event == "myEvent2") 
       myEvent2Handler = func;  
     }, 

     // public methods 
     method1: function (p) { 
      alert('method1 says:' + p); 
      MODULE.myEvent1(); 
     }, 
     method2: function (p) { 
      alert('method2 doing stuff'); 
      localFunc(p); 
      MODULE.myEvent2(); 
     } 

    }; 
}(); 

// register for events 
MODULE.addListener("myEvent1",function(){alert('fired1');}); 
MODULE.addListener("myEvent2",function(){alert('fired2');}); 

// use module (only event1 should fire!) 
MODULE.method1("hello"); 

Hãy thử nó ra:

http://jsfiddle.net/RqusH/3/

Có vẻ như rất nhiều công việc để có myEventx, myEventHandlerx, và addListener ?

+1

Khi bạn gọi 'addListener()', không phải là tạo 'myEvent1Handler' hoặc' myEvent2Handler' dưới dạng biến _global_ tham chiếu tham số 'func' được truyền vào? Nó sẽ không được thiết lập các thuộc tính của cùng một tên đã được định nghĩa trong đối tượng của bạn trừ khi bạn nói 'this.myEvent1Handler = ...' - và sau đó 'this.myEvent1Handler()' trong hàm 'myEvent1' của bạn. (Hoặc 'MODULE.myEvent1Handler' giống như cách bạn có' MODULE.myEvent1() 'trong' phương thức1'.) – nnnnnn

+0

Bạn đang cố giải quyết vấn đề gì? Điều này có vẻ như rất nhiều chi phí mà không thực sự làm bất cứ điều gì, nhưng làm cho một giàn giáo. Có lẽ nếu chúng tôi biết những gì bạn đang thực sự cố gắng hoàn thành, chúng tôi có thể giúp bạn tìm ra cách tốt nhất để làm điều đó. – jfriend00

+0

Cảm ơn ... Tôi muốn sự kiện trong MODULE, để người dùng MODULE có thể móc nối vào các sự kiện. Các phương thức MODULE sẽ có các yêu cầu async (sử dụng jquery) vì vậy tôi muốn sử dụng các sự kiện để chỉ ra khi một yêu cầu async đã hoàn thành. – ZimSystem

Trả lời

9

Thông thường, tôi sẽ không trả lời câu hỏi kiến ​​trúc với triển khai cụ thể (đặc biệt là phụ thuộc vào thư viện của bên thứ ba như jQuery), nhưng việc triển khai của tôi thúc đẩy khả năng sử dụng lại - và chúng tôi đang nói đến các mẫu ở đây một plugin jQuery nhỏ, $ .eventable, làm tăng thêm các đối tượng JavaScript với các phương thức sự kiện của jQuery.

Plugin này sẽ cho phép bạn triển khai khả năng xử lý sự kiện trên bất kỳ đối tượng nào (hoặc thể hiện lớp) bằng một cuộc gọi đơn giản.

jQuery.eventable = function (obj) { 
    // Allow use of Function.prototype for shorthanding the augmentation of classes 
    obj = jQuery.isFunction(obj) ? obj.prototype : obj; 
    // Augment the object (or prototype) with eventable methods 
    return $.extend(obj, jQuery.eventable.prototype); 
}; 

jQuery.eventable.prototype = { 

    // The trigger event must be augmented separately because it requires a 
    // new Event to prevent unexpected triggering of a method (and possibly 
    // infinite recursion) when the event type matches the method name 
    trigger: function (type, data) { 
    var event = new jQuery.Event(type); 
    event.preventDefault();     
    jQuery.event.trigger(event, data, this); 
    return this; 
    } 
}; 

// Augment the object with jQuery's event methods 
jQuery.each(['bind', 'one', 'unbind', 'on', 'off'], function (i, method) { 
    jQuery.eventable.prototype[method] = function (type, data, fn) { 
    jQuery(this)[method](type, data, fn); 
    return this; 
    }; 
}); 

Nếu bạn bao gồm đoạn đó, bạn có thể thực hiện giải pháp của bạn như thế này:

var MODULE = function() { 

    // private 
    var _field1; 
    var _field2; 

    function localFunc(p) { 
    alert('localFunc'); 
    } 

    // public 
    return $.eventable({ 

    // properties 
    prop1: _field1, 

    // public methods 
    method1: function(p) { 
     alert('method1 says:' + p); 
     this.trigger('myEvent1'); 
    }, 

    method2: function(p) { 
     alert('method2 doing stuff'); 
     localFunc(p); 
     this.trigger('myEvent2'); 
    } 

    }); 
}(); 

// register for events 
MODULE.on("myEvent1", function() { 
    alert('fired1'); 
}); 
MODULE.on("myEvent2", function() { 
    alert('fired2'); 
}); 

// use module (only event1 should fire!) 
MODULE.method1("hello"); 

MODULE của bạn bây giờ đã là phương pháp có thể được gọi như sau:

MODULE.on(event, /* data, */ handler); 
MODULE.bind(event, /* data, */ handler); 
MODULE.one(event, /* data ,*/ handler); 
MODULE.off(event, handler); 
MODULE.unbind(event, handler); 
MODULE.trigger(event /*, data */); 

đâu sự kiện là một space- danh sách các sự kiện được phân tách, trình xử lý là cuộc gọi lại của bạn và dữ liệu là một giá trị tùy chọn để chuyển đến các cuộc gọi lại của bạn.

Bạn có thể tham khảo jQuery's documentation để biết thêm chi tiết.

+0

Điều này nổi bật và phù hợp với mẫu mà tôi có xu hướng sử dụng hoàn hảo. Cảm ơn! Tôi sẽ cố gắng hết sức cẩn thận ... – Ricky

2

Mẫu mô-đun tiết lộ có bạn trả về một đối tượng ẩn danh. Thay vào đó, nếu bạn khai báo nó như là một biến và trả về nó có nghĩa là bạn có thể sử dụng các phương thức sự kiện jQuery chuẩn một cách dễ dàng, cả bên trong mô-đun để nâng cao các sự kiện và bên ngoài để trả lời chúng. Lưu ý rằng bạn phải chuyển nó thành một đối tượng jQuery trước.

var controller = (function() 
{ 
    function doAThing() 
    { 
    // Things getting done here 
    $(interface).trigger("complete"); 
    } 

    var interface = { 
    doAThing: doAThing 
    }; 
    return interface; 
})(); 

$(controller).on("complete", function() { console.log("Thing Done"); }); 
controller.doAThing(); 
Các vấn đề liên quan