Путаница в том, как работать с шаблоном модуля - PullRequest
0 голосов
/ 19 апреля 2019

Я запутался в том, как работать с шаблоном модуля (и шаблонами проектирования в целом) в JavaScript.

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

Вот как я с ним работаю:

Допустим, в моем приложении есть формы, которые я будуиспользовать для разных модулей (публиковать ветки, отвечать на ветки, комментировать гостевую книгу), с некоторым JavaScript, я дам пользователям некоторые функциональные возможности, такие как вывод пузыря смайлика и обработка вставки их в мои формы, отправка сообщений данныхна мой серверный код, чтобы вернуть HTML-код, чтобы добавить сообщение без перезагрузки страницы, я сделаю что-то вроде этого:

    let Form = function (selector_form, selector_textarea, selector_emoticonsButton, selector_postButton) {

      let form, textarea, emoticonsButton, postButton;
      let emoticonsBubble = new EmoticonsBubble()

      return {
        selectors: function () {
          return {
            form: function () { return selector_form },
            sendButton: function () { return selector_sendButton }
          }
        }

        setElements: function (obj) {
          form = $(obj).get(0);
          textarea = $(form).find(selector_textarea).get(0);
          emoticonsButton = $(form).find(emoticonsButton).get(0);
          postButton = $(form).find(selector_postButton).get(0);

          emoticonsBubble.setElements(form, emoticonsButton);
        },

        get: function () {
          return {
            form: function () { return form },
            //...
            emoticonsBubble: function () { return emoticonsBubble }
          }
        },

        post: function (moduleId, callback) {
          $.ajax({
          //parameters
          }).done(function (data) {
            callback(data);
          });
        }
      }
    }

    let EmoticonsBubble = function () {

      let thisContainerToAppendTo, thisTextarea;

      return {
        setElements: function (container, textarea) {
          thisContainerToAppendTo = container;
          thisTextarea = textarea;
        },

        pop: function () {
          this.ajax().pop(function (data) {
            $(thisContainerToAppendTo).append(data);
          });
        }

        insert: function (emoticon) {
          $(thisTextarea).append(emoticon);
        },

        ajax: function () {
          return {
            pop: function (callback) {
              $.ajax({
              //parameters
              }).done(function (data) {
                callback(data);
              });
            }
          }
        }
      }
    }

    // Events part

    let form = new Form('#threadForm', '.textarea', 'button[name="emoticons"]', 'button[name="send"]');
    let emoticonsBubble = form.get().emoticonsBubble();

    $(form.selectors().form()).on('click', function (e) {
      form.setElements(this);
    });

    $(form.selectors().sendButton()).on('click', function (e) {
      let moduleId = // retrieve module id, if it belongs to guests book, thread creation module or reply module
      form.post(moduleId, function (data) {
        // append data to something
      });
    });

    // etc for emoticons handling

Тот факт, что я должен переписать часть события для каждого другогоФорма, которую я имею в своем приложении, сохраняя все то же самое, но имя переменных, меня раздражает.

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

Ответы [ 3 ]

1 голос
/ 19 апреля 2019

Хорошо, шаблон для некоторых общих задач, которые у вас есть в части мероприятия, сводит вас с ума, верно?

Итак, проверяя свой код, вы можете исправить их многими способами.

A.Инкапсулируйте ваш код в реальные модули, я имею в виду это.

const Form = (function(/*receive here dependencies as arguments */){
  // your code module goes here 
})(/*inject dependencies here to module*/);

B.Вы можете создать шаблон событий для управления вашими внутренними и внешними событиями для модуля.

C.Вы знаете, какой слушатель нужен модулю, поэтому примените их в своем модуле.

Этот способ должен быть более пригоден для повторного использования, чем сейчас

1 голос
/ 19 апреля 2019

Шаблон модуля предназначен для предотвращения столкновения блоков кода с другими областями действия (обычно это глобальная область).

Как мы знаем, в JavaScript переменные определены с:

  • let и const относятся к родительскому блоку
  • var относятся к их содержащей функции (или Global, если не в функция)

Итак, если бы вы взяли свою Form функцию:

let Form = function (x,y,z) {

  let form, textarea, emoticonsButton, postButton;
  let emoticonsBubble = new EmoticonsBubble()

  return {
        . . . 
    }

    setElements: function (obj) {
        . . . 
    },

    get: function () {
        . . . 
    },

    post: function (moduleId, callback) {
        . . . 
    }
  }
}

Переменная Form является глобальной, потому что нет содержащего блока. Это проблема, потому что, если уже существует другой Глобал под названием Form (который вполне может быть из-за общего характера слова «Форма»). Таким образом, этот код не отрезает ваш код от разоблачения. Чтобы использовать шаблон модуля на нем, мы обернули бы его IIFE (выражением немедленного вызова функции), а внутри этого IIFE мы создали бы пользовательское пространство имен в глобальной области видимости, которого, как мы уверены, не существует (тем самым избегая имя коллизии):

(function(){
  // This is going to be exposed as publicly available via the module namespace
  function Form(x,y,z) {
    . . .
  }

  // This will remain private within the module
  function helper(){

  }

  // **********************************************************************    
  let temp = {};    // Create a temporary object to bind only the public API
  temp.Form = Form; // Bind the public members to the object

  // Expose the module to the Global scope by creating a custom namespace 
  // and mapping the temp object to it
  window.myCustomAPI = temp;
})();

// Now, outside of the module (in some higher scope), your public portions
// of the Module are accessible:
let myForm = new myCustomAPI.Form(arg, arg, arg);
1 голос
/ 19 апреля 2019

Повторение в вашем коде в основном происходит от выбора элементов и их помощников, и их легко можно абстрагировать в функцию:

  function Elements(selectors, children, options) {
    let elements = { ...children };

    return {
      selectors, 
      elements,
      setElements(obj) {                
        for(const [name, selector] of Object.entries(selectors)) 
           elements[name] = $(obj).find(selector).get(0);
        for(const child of Object.values(child))
           child.parent && child.parent(this, obj);
       },
       ...options
    }
 }

, которую затем можно использовать как:

  function Form(form, textarea, emoticonsButton, postButton) {
     const emoticonsBubble = EmoticonsBubble();

     return Elements({ form, textarea, emoticonButtons }, { emoticonsBubble }, {
       post() {
         //...
       }
    });
 }

 function EmoticonsBubble() {
   return Elements({ /*...*/ }, {}, {
      parent(parent, obj) {
        this.setElements(parent);
      }
   });
 }

Но вы в основном заново изобретаете здесь множество колес, задумывались ли вы об использовании одного из MVC, которые там есть (React, Vue, ...)?

...