关于javascript:jQuery和“有组织的代码”

jQuery and “Organized Code”

我最近一直在努力理解组织jquery代码的最佳方法。我之前问了另一个问题,我觉得我不够具体(在这里的这个问题中找到)。

我的问题是,应用程序越丰富,客户端越快失控。考虑这种情况…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//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命令中有几个级别,并开始怀疑在屏幕开始融化之前,还能添加多少逻辑。

我的问题是,人们如何管理或组织以限制其代码的复杂性?

我在另一篇文章中列出了我是如何做到这一点的…


只是想补充一下前面提到的内容:

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

可优化为:

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

这都是关于链接的,一种简化代码的好方法。


到目前为止,我是这样做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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中,函数是第一类对象,因此可以用作变量。


好吧,首先,拥有一个理解JavaScript的好的IDE可以非常有帮助,即使只是识别匹配的分界(大括号、parens等)。

如果你的代码真的开始变得如此复杂,考虑制作你自己的静态对象来组织混乱——你不必那么努力工作来保持所有的匿名性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();


有人写了一篇关于类似主题的文章。

jquery代码不必是丑陋的

例如,作者SteveWellens建议不要使用匿名函数,因为这会使代码更难阅读。相反,将函数引用推送到jquery方法中,如下所示:

1
2
3
4
5
6
7
$(document).ready(DocReady);

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

本文的另一个要点是将jquery对象分配给一个具体的变量,这使得代码看起来更干净,对实际的jquery对象的依赖性更低,并且更容易分辨某一行代码在做什么:

1
2
3
4
5
6
7
8
9
10
11
12
function ColorCodeTextBoxes()
{
    var TextBoxes = $(":text.DataEntry");

    TextBoxes.each(function()
    {
        if (this.value =="")
            this.style.backgroundColor ="yellow";
        else
            this.style.backgroundColor ="White";
    });
}


在我看来,Baileyp所描述的方法是我开始使用的方法,然后我通常将所有内容抽象成更多的可重用块,特别是当某些功能扩展到更容易将其抽象为插件的程度,然后将其特定于一个站点时。

只要将大块代码保存在单独的文件中并进行良好的编码,就可以得到一些真正干净的语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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() {});
    });
}

使用http://coffeescript.com/;)

1
2
3
4
5
6
7
8
$ ->
  container = $ '#inputContainer'
  for i in [0...5]
    $('<input/>').change ->
      $.ajax success: (data) ->
        for w in container.children()
          $(w).unbind().change ->
            alert 'duh'


我在你的另一篇文章中描述了我的方法。简短形式:

  • 不要混合使用JavaScript和HTML
  • 使用类(基本上开始将应用程序视为小部件的集合)
  • 只有一个$(document).ready(…)块
  • 将jquery实例发送到类中(而不是使用插件)

将一些anon函数粘贴到全局范围函数(或您自己的"namespace"对象)中,尤其是重用的函数中,它开始不像您发布的那样。有点像你所联系的。