Как использовать шаблон модуля javascript в реальном примере?

Я пытаюсь понять шаблон модуля JavaScript. Я видел примеры того, как он должен выглядеть, но я не понимаю, как его использовать.

Например, здесь происходит несколько вещей:

$('input#share').on("click", function() {

    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
        $("#messageempty").jmNotify();
        $('.remove_loading').remove();
    } else {
        addMessage(message);
    }

    return false;
});


function addMessage(message)
{
    $.ajax({
        url: '/test',
        type: 'POST',
        dataType: "json",
        data: {'message' : message},
        success: function(data) {
                ...
        },
        error: function() {
            ...
        }
    });
}

Как я могу использовать приведенный выше пример:

var myTest = function() {
    var selectId;
    function addMessage () {
        // ...
    }
    return { // public interface
        publicMethod1: function () {
            // all private members are accesible here
        }
    };
};
var start = myTest();

Где добавить событие click, объявить мои вары, добавить функцию addMessage с помощью вызова ajax. и вызовите функцию addMessage? Мне нужно обернуть все в $(document).ready(function()?

Может ли кто-нибудь пролить свет на это для меня?

Спасибо

Ответ 1

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

var myApp = (function() {

  var someElement = $("#foo"); //some element I know I'll use lots

  var addMessage = function(message) {
    $.ajax({
      url: '/test',
      type: 'POST',
      dataType: "json",
      data: {'message' : message},
      success: function(data) {
              ...
      },
      error: function() {
          ...
      }
    });
  };

  var inputClick = function(event) {
    event.preventDefault();
    //depending on if you'll reuse these selectors throughout the app I might have these as variables
    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
      $("#messageempty").jmNotify();
      $('.remove_loading').remove();
    } else {
      addMessage(message);
    }
  };

  var bindFunctions = function() {
    $("input#share").on("click", inputClick)
  };

  var init = function() {
    bindFunctions();
  };

  return {
    // EDIT: 27/12/16 - need to return init for 'usage' example to work
    init: init,
    addMessage: addMessage
    //anything else you want available
    //through myApp.function()
    //or expose variables here too
  };


})();

//usage

myApp.init();

Исходный код шаблона неправильный, функция должна иметь () в самом конце, чтобы сделать его функцией, которая немедленно вызывается, а затем выполняется, выставляя что-либо через return statement.

Возможно, вы захотите немного отличаться от того, что я сделал, это всего лишь базовая идея, но я надеюсь, что это может заставить вас начать.

Некоторое время назад задал вопрос, связанный с этим шаблоном, и Я ответил на него, объяснив, почему мы используем (function() {})(); и как работает оператор return в этом контексте, если вы немного смущены тем, что тоже стоит прочитать.

Ответ 2

Схема раскрывающего модуля используется следующим образом:

var moduleName = (function () {
    var privateVariable = 'private';

    var privateMethod = function () {
        alert('this is private');
    };

    // this is the "revealed" part of the module
    return { 
        publicVariable: 'public',
        publicMethod: function () {
            alert('this is public');
        }
    };
}());

Вы также можете определить общедоступные переменные/методы как приватные, а затем выставить ссылку на них, сделав их общедоступными. Это вопрос предпочтения.

В вашем примере, если вы хотите, чтобы addMessage был частью модуля, вы сделали бы это следующим образом:

var moduleName = (function () {
    // this becomes public due to the reference exposure in the return below
    var addMessage = function () {
        // do whatever
    };

    // this is the "revealed" part of the module
    return { 
        addMessage: addMessage
    };
}());

moduleName.addMessage();

Ответ 3

У меня есть некоторый опыт работы с Mootools, но я начинающий jQuery. Я прочитал документы, и, похоже, самый умный способ организовать код - это шаблон модуля, поэтому я пытаюсь это сделать. Однако одна вещь, которая, кажется, отсутствует в этом стиле, - это любое понятие "я" , так как каждая переменная внутри IIFE является автономным объектом (каламбур не предназначен).

Итак... может быть, это побеждает целую цель, но вы могли бы сделать что-то подобное, и все-таки иметь это "действительное" во всех способах, которыми стиль шаблона модуля действителен?

var feature = ( function () {

    var self = {

        config: {
            option1: 'thing 1',
            option2: 'thing 2'
        },


        init: function (options) {

            // allow overriding the default config
            jQuery.extend( self.config, options );

            self.doSomething();

        },

        doSomething: function () {

        },

    };

    return {
        init: self.init
    }

})();

Что мне нравится в этом, так это то, что я могу внутренне ссылаться на все методы и свойства, используя "я" . Я все еще могу разоблачить методы, которые мне нужны, используя объект "return", поэтому (я думаю), что все в порядке. Но я такой новичок, и это кажется таким простым и (на первый взгляд) изящным, что мне, должно быть, не хватает основной информации. Он разделяет стиль кодирования с форматом Object Literal, с которым я знаком с Mootools. Так что, возможно, я пытаюсь вставить круглую привязку в квадратную дыру. Возможно, внутренний литерал объекта не нужен, потому что вместо "self.doSomething()" я могу просто сказать "doSomething"? Это так?

Частично мне это нравится, потому что я могу установить аргумент "context" для $.ajax как "я" , который кажется победой.

Ответ 4

Идея состоит в том, чтобы сократить видимость из внешнего мира и улучшить управление кодом, разделив ваш код на сегменты/модули. Проверьте это, если вы хотите увидеть действительно хорошее использование модульного шаблона проектирования и каким-то образом получить от этого выгоду. http://learn.jquery.com/code-organization/concepts/

Ответ 5

В отличие от JAVA, у Javascript нет концепции частного и публичного доступа к свойствам или методам. Позволяет создать объект с именем person, который имеет 2 свойства firstName и lastName, а также создать 2 функции, которые будут getters для наших свойств. В Javascript мы можем создавать функции как свойства объектов, и эти функции доступны как любое другое свойство в любом месте.

var person={
  "firstName":"Anoop",
  "lastName":"Rai",
  "getFirstName":function(){
    return this.firstName;
  },
  "getLastName":function(){
    return this.lastName;
  }
};
console.log(person.getFirstName());
console.log(person.firstName);

Как и ожидалось выше, коды 11 печатают Anoop и Anoop. Хм, это плохо для объектно-ориентированного программирования. Ну, мы успешно реализовали геттеры, и поэтому у нас также должны быть сеттеры, которые должны быть общедоступными, а свойства должны быть помечены как закрытые области (что эти частные и публичные концепции принадлежат JAVA, С++, как языки). Наши намерения хороши, позволяют применять концепции, специфичные для Javascript. Мы не хотим делать person.firstName, мы хотим предотвратить доступ к собственности напрямую. В таких языках, как JAVA из-за частных и публичных, мы достигли контролируемого доступа к свойствам, но в Javascript все открыто.

Javascript использует концепцию закрытий для реализации таких вещей, как частные и публичные. Этот шаблон называется шаблоном модуля. То есть, скрывая переменные от открытого доступа. Чтобы реализовать области действия, заверните свои коды в функции (помните, что области применения реализованы через функции в Javascript).

function createPerson(){
  var returnObj={
    "firstName":"Anoop",
    "lastName":"Rai",
    "getFirstName":function(){
      return this.firstName;
    },
    "getLastName":function(){
      return this.lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

Теперь также над строками печатает Anoop и Anoop. Все еще нет успеха. Пока свойства привязаны к объекту, к нему будут обращаться напрямую. Давайте развяжем его. Вместо свойств мы делаем переменные области действия (замыкающие переменные).

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

Теперь над строками печатается Anoop и undefined. Как это произошло? Из-за закрытий, когда были созданы функции getFirstName и getLastName, функции имели целую цепочку областей видимости или указатели на соответствующие переменные, то есть firstName и lastName. Объект returnObj не помнит переменные, но объекты функции запоминаются из-за закрытия. Похоже, мы достигли того, чего хотели, но осталось одно, и это сеттеры для контролируемого доступа firstName и lastName. Позволяет реализовать сеттеры.

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    },
    "setFirstName":function(name){
      return firstName=name;
    },
    "setLastName":function(name){
      return lastName=name;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
person.setFirstName("Kumar");
console.log(person.getFirstName());

Мы успешно модифицировали firstName, но контролируемым образом.

http://jkoder.com/the-module-pattern-javascript-way-of-hiding-data-in-objects-from-public-access/