как использовать шаблон модуля 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();

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

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

Спасибо


person Patrioticcow    schedule 20.08.2012    source источник


Ответы (5)


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

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 работает в этом контексте, если вас это немного смущает, возможно, вам тоже стоит прочитать.

person Jack Franklin    schedule 20.08.2012
comment
что, если у меня есть больше методов addMessage и inputClick, нужно ли мне создавать больше методов, подобных bindFunctions, и добавлять их все в основной класс и в возвращаемый? - person Patrioticcow; 20.08.2012
comment
Если у вас есть другие методы, которые возникают при событии, я бы привязал их все к методу bindFunctions, аналогично тому, как я сделал это с одним методом события выше. Пожалуйста, не принимайте это как истину - если вы предпочитаете использовать немного другие имена функций или размещать их немного по-другому, продолжайте :) - person Jack Franklin; 20.08.2012
comment
в моем случае у меня есть несколько событий щелчка, и каждое из них вызывает метод ajax, это какой-то король ситуации в чате. Но мне интересно, почему я вызываю myApp.init();, когда возвращаю addMessage. Что, если у меня есть больше возвратов, например addMessage: addMessage, addMessage1: addMessage1, etc, как мне убедиться, что каждый щелчок вызывает правильный метод и возвращает правильный возврат? :) - person Patrioticcow; 20.08.2012
comment
или, возможно, вы имели в виду myApp.addMessage(); - person Patrioticcow; 20.08.2012
comment
Вы не должны возвращать addMessage, это был просто пример, показывающий, как вы можете возвращать методы. Просто верните то, что вам может понадобиться для доступа извне. - person Jack Franklin; 20.08.2012
comment
спасибо, я думаю, что теперь я понимаю это лучше, плохо перехожу к практике. - person Patrioticcow; 20.08.2012
comment
С опозданием на 3 года, но просто уточняю, в вашем примере кода вы не можете использовать myApp.init(); так как вы не вернули функцию init(), верно? спасибо за объяснение еще раз. - person Nitish Dhar; 28.03.2015

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

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();
person jbabey    schedule 20.08.2012
comment
я подумал, почему бы не создать метод с событием click и еще один с вызовом ajax, затем еще один, который связывает эти 2 вместе, а затем возвращает этот... что вы думаете? - person Patrioticcow; 20.08.2012
comment
@Patrioticcow да, вы можете создать их оба как частные методы, и тогда публичный метод будет вызывать их оба. хорошо, когда как можно меньше кода выставлено на всеобщее обозрение. - person jbabey; 20.08.2012

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

person kta    schedule 17.10.2013

В отличие от JAVA, в Javascript нет концепции приватного и общедоступного для свойств или методов. Давайте создадим объект с именем person, который имеет 2 свойства firstName и lastName, а также создадим 2 функции, которые будут геттерами для наших свойств. В 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, C++). У нас хорошие намерения, давайте применим концепции, характерные для 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/

person Anoop Rai    schedule 01.09.2016

У меня есть некоторый опыт работы с 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
    }

})();

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

Отчасти мне это нравится, потому что я могу установить аргумент «контекст» $.ajax как «я», что кажется выигрышным.

person hairbo    schedule 08.08.2013