2011-11-11 3 views
13

私はモジュールパターンを実装しており、イベントリスナ/ハンドラを定義して登録するための最良の方法を知りたいと思います。以下の作品は、多分、より良い/簡単な方法があります...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"); 

はそれを試してみてください:

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

はmyEventx、myEventHandlerx、とのaddListenerを持っている多くの作業のように思えます?

+1

あなたは 'のaddListener()'を呼び出すと、渡された 'func'パラメータを参照_Global_変数として' myEvent1Handler'または 'myEvent2Handler'を作成するということではないでしょうか? 'myEvent1'関数で' this.myEvent1Handler = ... ' - そして' this.myEvent1Handler() 'と言う以外は、あなたのオブジェクトにすでに定義されている同じ名前のプロパティを設定しません。 (あるいは 'MODULE.myEvent1Handler'は' method1'に 'MODULE.myEvent1()'を持っているようです。) – nnnnnn

+0

あなたは実際どのような問題を解決しようとしていますか?これは実際には何もしませんが足場を作るオーバーヘッドのようです。おそらく、実際に達成しようとしていることが分かっていれば、それを実行する最良の方法を見つける手助けをすることができます。 – jfriend00

+0

ありがとう... MODULEのユーザーがイベントにフックできるように、私はMODULEでイベントを起こしたいと思います。 MODULEメソッドは非同期要求(jqueryを使用)を持つので、イベントを使用して非同期要求が完了したことを示したいとします。 – ZimSystem

答えて

9

通常、具体的な実装(特にjQueryのようなサードパーティのライブラリに依存するもの)のアーキテクチャ上の質問には反応しませんが、私の実装は再利用性を促進するため、ここでパターンを話しています。小さなjQueryプラグイン、$ .eventableは、jQueryのイベントメソッドでJavaScriptオブジェクトを補強します。

このプラグインを使用すると、すべてのオブジェクト(またはクラスインスタンス)に対して1回の簡単な呼び出しでイベント処理機能を実装できます。

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(); 
関連する問題