jQuery и организованный код

В последнее время я изо всех сил пытался понять, как лучше всего организовать код jQuery. Я задал другой вопрос ранее и не думаю, что я был достаточно конкретным (найдено в этот вопрос здесь).

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

//Let's start some jQuery
$(function() {        
    var container = $("#inputContainer");

    //Okay let's list text fields that can be updated
    for(var i=0; i < 5; i++) {

        //okay let's add an event for when a field changes
        $("<input/>").change(function() {

            //okay something changed, let's update the server
            $.ajax({
                success:function(data) {

                    //Okay - no problem from the server... let's update
                    //the bindings on our input fields
                    $.each(container.children(), function(j,w) {

                        //YIKES!! We're deep in here now!!
                        $(w).unbind().change(function() {

                            //Then insanity starts...

                        }); // end some function

                    }); //end some loop

                } // what was this again?

            }); //ending something... not sure anymore

        }).appendTo(container); //input added to the page... logic WAY split apart

    }; //the first loop - whew! almost out!

});  //The start of the code!!

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

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

Я перечислил, как я это делаю, в другом посте ...


person hugoware    schedule 30.10.2008    source источник
comment
.changed (... должно быть .change (...   -  person Már Örlygsson    schedule 31.10.2008
comment
Вы правы - я сделал это по памяти ... что для меня не самое лучшее ...   -  person hugoware    schedule 31.10.2008
comment
Не могли бы вы тогда отредактировать сообщение и исправить его? Вызвали у меня замешательство, пока я читал один из ответов.   -  person montrealist    schedule 01.06.2009
comment
@Hugoware, я думаю, тебе стоит принять ответ :)   -  person Lipis    schedule 09.12.2012


Ответы (8)


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

$.each(container.children(), function(j,w) {
    $(w).unbind().change(function() { ... });
});

можно оптимизировать для:

container.children().unbind().change(function() { ... });

Все дело в цепочках - отличном способе упростить код.

person John Resig    schedule 31.10.2008
comment
А читать ваш код еще интереснее - я не понимал, что вам не нужно перебирать каждый элемент ... очень круто - person hugoware; 01.11.2008
comment
пффф, что бы ВЫ знали, Джон. - person nickf; 05.11.2008
comment
Что здесь означает «оптимизированный»? Код работает быстрее или можно сократить длинный фрагмент кода? Я думаю, что это последнее, но я думал, что просил убедиться. - person Kevin Le - Khnle; 12.01.2009
comment
@Khnle: Я так понимаю: код проще, короче, легче читать. Маловероятно, что это сильно повлияет на время выполнения. - person thomasrutter; 19.03.2010

Пока делаю так:

// initial description of this code block
$(function() {        
    var container = $("#inputContainer");

    for(var i=0; i < 5; i++) {
        $("<input/>").changed(inputChanged).appendTo(container);
    }; 

    function inputChanged() {
        $.ajax({
            success: inputChanged_onSuccess
        });
     } 

     function inputChanged_onSuccess(data) {
        $.each(container.children(), function(j,w) {
          $(w).unbind().changed(function() {
             //replace the insanity with another refactored function
          });
        });
      }
});

В JavaScript функции являются первоклассными объектами и поэтому могут использоваться как переменные.

person David Alpert    schedule 30.10.2008
comment
Мне тоже нравится этот подход - держать все в секрете. Если вы не хотите, чтобы некоторые методы были общедоступными;) - person Peter Bailey; 31.10.2008
comment
согласованный; этот подход не оставляет никаких проблем в глобальном пространстве имен, поскольку он инкапсулирует все внутри анонимного закрытия. Функциональный стиль jQuery тяготеет к этому шаблону. Шаблон ООП Крокфорда в ответе BaileyP полезен, когда вам понадобится ссылка на свой блок кода позже. - person David Alpert; 31.10.2008

Ну, во-первых, наличие хорошей IDE, которая понимает javascript, может очень помочь, даже если просто определить соответствующие демаркации (фигурные скобки, скобки и т. Д.).

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

var aCustomObject = {
    container: $("#inputContainer"),
    initialize: function()
    {
        for(var i=0; i < 5; i++)
        {
            $("<input/>").changed( aCustomObject.changeHandler );
        }
    },
    changeHandler: function( event )
    {
        $.ajax( {success: aCustomObject.ajaxSuccessHandler} );
    },
    ajaxSuccessHandler: function( data )
    {
        $.each( aCustomObject.container.children(), aCustomObject.updateBindings )
    },
    updateBindings: function( j, w )
    {
        $(w).unbind().changed( function(){} );
    }
}
aCustomObject.initialize();
person Peter Bailey    schedule 30.10.2008
comment
Я хочу проголосовать за то, что вы упомянули о преимуществах хорошей IDE, но я хочу проголосовать против вас за предложение использовать объекты для организации кода в отличие от их предполагаемой функции. - person matt lohkamp; 05.11.2008
comment
с другой стороны, возможно, вы не собираетесь использовать объекты в качестве организационных элементов, исключая другие соображения, поэтому я предоставлю вам право сомневаться. - person matt lohkamp; 05.11.2008
comment
Цель объекта не обязательно связана с организацией, хотя это приятное дополнительное преимущество, но с минимальным потреблением глобального пространства имен. Я вообще не думаю, что это противоречит их прямому назначению. Такой тип мышления крайне ограничивает. - person Peter Bailey; 05.11.2008

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

Пока вы храните большие блоки кода в отдельном файле и хорошо кодируете, вы можете получить действительно чистый синтаксис.

// Page specific code
jQuery(function() {
    for(var i = 0; i < 5; i++) {
         $("<input/>").bindWithServer("#inputContainer");
    }
});

// Nicely abstracted code
jQuery.fn.bindWithServer = function(container) {
     this.change(function() {
             jQuery.ajax({
                 url: 'http://example.com/',
                 success: function() { jQuery(container).unbindChildren(); }
             });
     });
}
jQuery.fn.unbindChildren = function() {
    this.children().each(function() {
        jQuery(this).unbind().change(function() {});
    });
}
person user32924    schedule 30.10.2008

Кто-то написал сообщение на аналогичную тему.

Код jQuery не обязательно должен быть уродливым

Например, автор, Стив Велленс, предлагает не использовать анонимные функции, так как это затрудняет чтение кода. Вместо этого вставьте ссылку на функцию в методы jQuery, например:

$(document).ready(DocReady);

function DocReady()
{       
    AssignClickToToggleButtons();
    ColorCodeTextBoxes();
}

Еще один вывод из статьи - назначить объект jQuery конкретной переменной, что сделает код более чистым, менее зависимым от фактического объекта jQuery и легче определить, что делает определенная строка кода:

function ColorCodeTextBoxes()
{
    var TextBoxes = $(":text.DataEntry");

    TextBoxes.each(function()
    {
        if (this.value == "")
            this.style.backgroundColor = "yellow";
        else
            this.style.backgroundColor = "White";
    });
}
person Irfan    schedule 02.02.2010
comment
Сначала я пометил это как не ответ, но потом понял, что у меня достаточно опыта, чтобы исправить себя, поэтому я отредактировал это, чтобы добавить некоторый контент из ссылки, так что, если он сломается, этот пост все равно будет полезен будущим посетителям. Надеюсь это поможет! - person jmort253; 10.05.2014

Вставьте некоторые из анонимных функций в функции глобальной области видимости (или ваш собственный объект «пространства имен»), особенно повторно используемые функции, и он начнет меньше походить на то, что вы опубликовали. Вроде того, на что вы ссылались.

person Josh    schedule 30.10.2008

Я описал свой подход в другом вашем сообщении. Короткая форма:

  • не смешивайте javascript и HTML
  • использовать классы (в основном начинайте видеть ваше приложение как набор виджетов)
  • есть только один блок $ (document) .ready (...)
  • отправлять экземпляры jQuery в свои классы (вместо использования плагинов)
person Jason Moore    schedule 12.11.2008

Используйте http://coffeescript.com/;)

$ ->
  container = $ '#inputContainer'
  for i in [0...5]
    $('<input/>').change ->
      $.ajax success: (data) ->
        for w in container.children()
          $(w).unbind().change ->
            alert 'duh'
person Aldo Bucchi    schedule 28.10.2010
comment
Не совсем понимаю, как это поможет ОП. Но в любом случае +1 за то, что показал мне что-то новое и интересное. - person Robert Harvey; 28.10.2010
comment
Я ответил на этот вопрос более 3 лет назад, и это считается отрицательной репутацией? В наши дни все крутые ребята используют Coffeescript. - person Aldo Bucchi; 24.11.2013
comment
Я предполагаю, что люди не понимают, как использование CoffeeScript отвечает на исходный вопрос. Каким бы полезным это ни было, использование CoffeeScript не требует определенной организации вашего кода. - person Trevor; 24.01.2014