Использование шаблона модуля с обработчиками событий

#javascript #jquery #javascript-events

#javascript #jquery #jquery-события

Вопрос:

Мой запрос касается эффективного использования шаблонов модулей JavaScript. Ниже приведен упрощенный модуль из моего кода. Я хочу разделить его на модули. Модули будут иметь несколько 100 LOC каждый.

Вопрос: Какой из методов 1 против 2 против 3 лучше? В методе 1 бесполезно создавать новый объект каждый раз, когда мышь наводится на элемент? Пожалуйста, не стесняйтесь критиковать / предлагать альтернативную реализацию.

Контекст: у меня есть несколько десятков элементов с .myclass атрибутом, которые нуждаются в случайной обработке событий в течение всего срока службы веб-страницы.

 (function ($) {

  var MyModule = function (element) {
      this.element = element
  }

  MyModule.prototype.color1 = function () {
      $(this.element).css('backgroundColor', '#aaa');
  }

  MyModule.prototype.color2 = function () {
      $(this).css('backgroundColor', '#aaa');
  }

  //Event handlers for MyModule 
  $('#mydiv').on('mouseenter', '.myclass', function(evt) {
      //Method 1
      var myMod = new MyModule(this);
      myMod.color1();

      //Method 2
      MyModule.prototype.color2.call(this)          
  });

  $('body').on('mouseleave', function(evt) {...});


})(jQuery);
  

Обновить

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

Альтернативная реализация с использованием объектного литерала

 ... Code Removed ...
  

Ответ №1:

прототипирование — одна из замечательных особенностей javascript, но здесь вы используете его совершенно неправильно, нет необходимости в том, чтобы этот шаблон делал что-то такое простое, как

 jQuery(function($) {

    $('#mydiv').on({
        mouseenter: function(evt) {
            $(this).css('backgroundColor', '#aaa');
        },
        mouseleave: function(evt) {

        }
    }, '.myclass');

});
  

создание нового экземпляра объекта для получения элемента и изменения его цвета на самом деле не то, что вам нужно делать.

Комментарии:

1. Согласен. Однако это упрощенная версия кода. На самом деле это несколько тысяч строк, и я хочу разделить их на модули. Каждый модуль состоит из нескольких 100 строк и имеет дюжину методов. Имея в виду это и ремонтопригодность / модульность, что бы вы предложили?

2. Я бы посоветовал держаться подальше от прототипов, если вам на самом деле не нужен новый экземпляр класса, а вы просто используете его для разделения кода, а вместо этого разбиваете код на блоки и функции и, возможно, даже используете литералы, если это соответствует тому, что вы делаете.

3. Не могли бы вы предложить вариант использования, расширив приведенный выше пример, где на самом деле было бы полезно иметь новый экземпляр class ?

4. @buffer — я действительно не могу придумать никаких веских причин для использования этого шаблона с jQuery таким образом. У jQuery есть свой собственный способ сделать это с $.fn помощью плагинов и, поэтому для использования прототипов должно было быть что-то чертовски особенное.

5. Я использовал некоторые стили кодирования из модального диалогового окна Bootstrap: пример .

Ответ №2:

В ваших примерах, похоже, предполагается, что вам нужно создать некоторый объект MyModule или пространство имен, когда вы используете шаблон модуля. На мой взгляд, это неверно.

В ваших значительно упрощенных примерах нет необходимости, чтобы созданный MyModule находился вне IIFE, потому что вы не возвращаете объект MyModule снаружи и не назначаете его какому-либо глобальному пространству имен. Но что важно, это мотивация для выбора между альтернативами 1, 2 и 3. Нужно ли вам создавать экземпляр при каждом вызове, можете ли вы обойтись созданием только одноэлементного экземпляра или можете ли вы просто назначить функцию в замыкании, зависит от того, что на самом деле должен делать обработчик событий, а не от теоретического обсуждения рекомендаций по шаблону модуля. Ни одна из упомянутых вами альтернатив не оказывает никакого влияния на модульность кода.

В приведенном примере, как написано, есть четвертая альтернатива, которая более эффективна, чем три, которые вы упомянули

 (function ($) {
  var MyModule = {
    color : function (evt) {
      // I'm not sure whether you want this or evt.target
      $(this).css('backgroundColor', '#aaa');
    }  
  }

  //Event handlers for MyModule 
  $('#mydiv').on('mouseenter', '.myclass', MyModule.color);
})(jQuery);
  

Вам не нужно создавать новый обработчик экземпляра функции для каждого элемента DOM, к которому вы подключаетесь. Информация о событии автоматически передается функции и this является элементом DOM, к которому привязан обработчик. Обе эти данные передаются обработчику с помощью jQuery on, потому что именно так необработанный JavaScript браузера обрабатывает события. Если это вся информация, необходимая вашему обработчику для выполнения своей работы, тогда вам нужен только один экземпляр вашего обработчика.

Комментарии:

1. Я следую шаблону кода, используемому Bootstrap здесь: github.com/twbs/bootstrap/blob/master/js/modal.js (без создания плагина jQuery). Я понимаю, что текущий пример можно легко упростить до объектного литерала. Однако я пытаюсь понять, какой эффективный способ ссылаться на модуль внутри его обработчиков событий? Если бы я придерживался шаблона модуля. Я, вероятно, исключу метод 3 по педагогическим соображениям.

2. То, что наиболее эффективно, зависит от того, что вам нужно сделать — правильный ответ зависит от ситуации, и универсального ответа не существует. Есть несколько общих принципов, но у принципов есть много исключений.