События шаблона Javascript и слушатели - PullRequest
13 голосов
/ 12 ноября 2011

Я реализую шаблон модуля и хотел бы знать лучший / предпочтительный способ определения и регистрации прослушивателей / обработчиков событий. Следующее работает, но, возможно, есть лучший / более простой способ ...

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?

Ответы [ 2 ]

8 голосов
/ 01 августа 2012

Обычно я не отвечал бы на архитектурный вопрос с конкретной реализацией (особенно зависимой от сторонней библиотеки, такой как jQuery), но, поскольку моя реализация поддерживает повторное использование - и мы здесь обсуждаем шаблоны - я представлюнебольшой плагин jQuery, $ .eventable, который дополняет объекты JavaScript с помощью методов событий 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 .

4 голосов
/ 23 октября 2015

Шаблон показательного модуля заставляет вас возвращать анонимный объект. Если вместо этого вы объявляете его как переменную и возвращаете его, это означает, что вы можете довольно легко использовать стандартные методы событий 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();
...