2011-11-11 16 views
13

मैं मॉड्यूल पैटर्न को कार्यान्वित कर रहा हूं, और ईवेंट श्रोताओं/हैंडलरों को परिभाषित और पंजीकृत करने के लिए सबसे अच्छा/पसंदीदा तरीका जानना चाहता हूं। काम करता है निम्नलिखित, लेकिन शायद ही कोई बेहतर/आसान तरीका है ...जावास्क्रिप्ट मॉड्यूल पैटर्न घटनाक्रम और श्रोताओं

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"); 

इसे आजमाएं:

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

बहुत काम की तरह लगता है myEventx, myEventHandlerx, और addListener के लिए ?

+1

जब आप फोन 'addListener()', बनाने 'myEvent1Handler' या' myEvent2Handler' _global_ चर 'func' पैरामीटर संदर्भित में पारित के रूप में है कि नहीं है? यह आपके ऑब्जेक्ट में पहले से परिभाषित उसी नाम के गुणों को सेट नहीं करेगा जबतक कि आप 'this.myEvent1Handler = ...' - और फिर 'my.myEvent1 हैंडलर()' को अपने 'myEvent1' फ़ंक्शन में' कहते हैं। (या 'MODULE.myEvent1 हैंडलर 'जैसे कि' method1' में आपके पास 'MODULE.myEvent1()' है।) – nnnnnn

+0

वास्तव में आप किस समस्या को हल करने की कोशिश कर रहे हैं? ऐसा लगता है कि बहुत सारे ओवरहेड हैं जो वास्तव में कुछ भी नहीं करते हैं बल्कि मचान बनाते हैं। शायद अगर हम जानते थे कि आप वास्तव में क्या करने की कोशिश कर रहे थे, तो हम आपको ऐसा करने का सबसे अच्छा तरीका खोजने में मदद कर सकते हैं। – jfriend00

+0

धन्यवाद ... मैं मॉड्यूल में ईवेंट करना चाहता हूं, ताकि मॉड्यूल का उपयोगकर्ता ईवेंट में शामिल हो सके। मॉड्यूल विधियों में एसिंक अनुरोध (jquery का उपयोग करके) होगा, इसलिए मैं ईवेंट का उपयोग करना चाहता हूं ताकि यह इंगित किया जा सके कि एक async अनुरोध कब पूरा हो गया है। – ZimSystem

उत्तर

9

आम तौर पर, मैं एक विशिष्ट कार्यान्वयन (विशेष रूप से एक तृतीय पक्ष पुस्तकालय जैसे jQuery पर निर्भर) के साथ एक वास्तुशिल्प प्रश्न का जवाब नहीं दूंगा, लेकिन चूंकि मेरा कार्यान्वयन पुन: प्रयोज्यता को बढ़ावा देता है - और हम यहां पैटर्न की बात कर रहे हैं - मैं प्रस्तुत करूंगा एक छोटी jQuery प्लगइन, $ .eventable, जो jQuery की घटना विधियों के साथ जावास्क्रिप्ट ऑब्जेक्ट्स को बढ़ाता है।

यह प्लगइन आपको एक साधारण कॉल के साथ किसी ऑब्जेक्ट (या क्लास इंस्टेंस) पर इवेंट हैंडलिंग क्षमता को लागू करने की अनुमति देगा।

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

आपको लगता है कि स्निपेट शामिल हैं, तो आप इस तरह अपने समाधान को लागू कर सकते हैं:

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.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 */); 

कहाँ घटना एक अंतरिक्ष है घटनाओं की सीमित सूची, हैंडलर आपका कॉलबैक है, और डेटा आपके कॉलबैक को पास करने के लिए एक वैकल्पिक मान है।

अधिक जानकारी के लिए आप jQuery's documentation देख सकते हैं।

+0

यह बकाया है और पैटर्न का मिलान करता है जो मैं पूरी तरह से उपयोग करता हूं। धन्यवाद! मैं इस बहुत सावधानी से काम करने जा रहा हूं ... – Ricky

2

खुलासा मॉड्यूल पैटर्न आपने एक अज्ञात ऑब्जेक्ट वापस कर दिया है। यदि आप इसे एक चर के रूप में घोषित करते हैं और इसे वापस कर देते हैं तो इसका मतलब है कि आप मानक jQuery ईवेंट विधियों का उपयोग मॉड्यूल के अंदर घटनाओं को बढ़ाने और बाहरी रूप से जवाब देने के लिए आसानी से कर सकते हैं। ध्यान दें कि आपको इसे पहले से ही एक jQuery ऑब्जेक्ट में बदलना होगा।

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(); 
संबंधित मुद्दे