代码之家  ›  专栏  ›  技术社区  ›  Andrew

如何干燥我的jQuery代码并使其更可读/更易维护?

  •  3
  • Andrew  · 技术社区  · 14 年前

    <script type="text/javascript">
    
    $(document).ready(function(){
        $('#registration-information .copy-button').click(copyField);
    });
    
    function copyField(e) {
    
        e.preventDefault();
    
        var $tr = $(this).closest('tr');
        var originalText = jQuery.trim($tr.find('.contact-data').text());
        var newText = jQuery.trim($tr.find('.registration-data').text());
        var $button = $tr.find('.copy-button');
        var $loadingIcon = $('<span class="loading-icon"></span>').hide().insertAfter($button);
        var $undoLink = $('<a class="undo-link" href="#">Undo</a>').hide().insertAfter($button);
        var field = $button.attr('id');
    
        $undoLink.click(function(e){
            e.preventDefault();
            undoCopyField($tr, originalText);
        });
    
        $button.hide();
        $loadingIcon.show();
    
        $.ajax({
            url: '/registrations/copy-field-to-contact',
            data: {
                id: '<?php echo $registration->ID ?>',
                field: field,
                data: newText
            },
            success: function(data){
                if (data.success) {
                    $loadingIcon.hide();
                    $tr.find('.contact-data').html(newText);
                    $tr.find('td.form_field_label').removeClass('mismatched');
                    $tr.effect('highlight', 1000, function(){
                        $undoLink.fadeIn();
                    });
                } else {
                    displayErrorMessage(data.error);
                    $loadingIcon.hide();
                    $button.show();
                }
            },
            error: function(){
                displayErrorMessage('Unknown reason');
                $loadingIcon.hide();
                $button.show();
            }
        });
    }
    
    function undoCopyField($tr, originalText) {
    
        var $button = $tr.find('.copy-button');
        var $loadingIcon = $tr.find('.loading-icon');
        var $undoLink = $tr.find('.undo-link');
        var field = $button.attr('id');
    
        $undoLink.hide();
        $loadingIcon.show();
    
        $.ajax({
            url: '/registrations/copy-field-to-contact',
            data: {
                id: '<?php echo $registration->ID ?>',
                field: field,
                data: originalText
            },
            success: function(data){
                if (data.success) {
                    $undoLink.remove();
                    $loadingIcon.hide();
                    $tr.find('.contact-data').html(originalText);
                    $tr.find('td.form_field_label').addClass('mismatched');
                    $tr.effect('highlight', 1000, function(){
                        $tr.find('.copy-button').fadeIn();
                    });
                } else {
                    displayErrorMessage(data.error);
                    $loadingIcon.hide();
                    $undoLink.show();
                }
            },
            error: function(){
                displayErrorMessage('Unknown reason');
                $loadingIcon.hide();
                $undoLink.show();
            }
        });
    }
    
    function displayErrorMessage(message) {
        alert('Sorry, there was an error while trying to save your changes: ' + message);
    }
    </script>
    

    此代码示例中有许多部分包含几乎相同的代码块。特别是AJAX调用。这两个块基本上是相同的,除了调用完成后发生的操作。我真的很想想出一个办法把那些部分擦干。

    6 回复  |  直到 14 年前
        1
  •  3
  •   Adrian Grigore    14 年前

    两个提示:

    `

    var MyCode=MyCode||{
            copyField:function (e){
        },
            someOtherFunction:function(){
        }
    };
    
        $(document).ready(function(){
            MyCode.copyField(...);
        });
    
    • 将javascript代码放在一个或多个单独的文件中(每个名称空间一个),并使用第三方库,如 combres
        2
  •  2
  •   Simon Dyson    14 年前

    使jQuery代码更干净、更易于维护的一种方法是将其分解为可重用的jQuery插件。这允许您将相关功能封装在单个文件中。每个插件实际上都是一个名称空间,因此可以避免函数名冲突。您还可以将参数传递给插件,以便在逐页或逐例的基础上自定义行为。

    here

        3
  •  0
  •   treeface    14 年前

    我在这里看到的唯一一个真正的可读性问题是,您可以在不使用 var 每次在每个变量后使用逗号:

    var $tr = $(this).closest('tr'),
        originalText = jQuery.trim($tr.find('.contact-data').text()),
        newText = jQuery.trim($tr.find('.registration-data').text());
    

    我总是觉得这比一系列变量更容易理解。在眼睛看来,它就像一个以 变量 当缩进返回时结束。

    除此之外,一切看起来都不错。

        4
  •  0
  •   jeffo    14 年前

    首先。。。

    重构以消除重复。

    限制全局范围的使用。

    阅读干净的代码:敏捷软件工艺手册[平装本] 罗伯特C.马丁(编辑)

        5
  •  0
  •   Anoop    14 年前

    创建顶级对象(命名空间) 让var STW={};

    STW.namespace = function () {
                var a = arguments, o = null, i, j, d;
                for (i = 0; i < a.length; i = i + 1) {
                    d = ("" + a[i]).split(".");
                    o = STW;
                    for (j = (d[0] == "STW") ? 1 : 0; j < d.length; j = j + 1) {
                        o[d[j]] = o[d[j]] || {};
                        o = o[d[j]];
                    }
                }
                return o;
            }
    

    使用STW.namespace名称空间("STW.namespace1名称空间");

    //你的代码 在其他文件中 STW.namespace名称空间("STW.namespace1名称空间.namespace2“); STW.namespace1名称空间.namespace2.class2=函数(){

    //你的代码

        6
  •  0
  •   Erik Reppen    14 年前

    与任何基于c的函数一样,$.ajax parens中的内容只是一个参数。

    {}是JS对对象的文字表示。因此,如果两种情况在{}之间有相同的内容,您可以这样做:

        options = {
            url: '/registrations/copy-field-to-contact',
            data: {
                id: '<?php echo $registration->ID ?>',
                field: field,
                data: newText
            },
            success: function(data){
                if (data.success) {
                    $loadingIcon.hide();
                    $tr.find('.contact-data').html(newText);
                    $tr.find('td.form_field_label').removeClass('mismatched');
                    $tr.effect('highlight', 1000, function(){
                        $undoLink.fadeIn();
                    });
                } else {
                    displayErrorMessage(data.error);
                    $loadingIcon.hide();
                    $button.show();
                }
            },
            error: function(){
                displayErrorMessage('Unknown reason');
                $loadingIcon.hide();
                $button.show();
            }
        }
    

    对于这两种情况:

    $.ajax(options);
    

    如果下一个ajax调用的选项有变化:

    options.url = "http://www.google.com";
    $.ajax(options);
    

    示例#2-更改数据属性(另一个对象)的id属性

    options.data.id = "newID";
    

    关于JQuery选择器语法的一点注意事项。通过身份证直接抓取是理想的。只按类抓取在旧版本的IE中可能会非常慢(没有本地getByClassName方法,所以会有更多的解释器级循环)。编写选择器的理想方法是先将范围缩小到最接近的父ID,如果可以显式地将标记名添加到后续的类选择器以进一步缩小范围(getElementsByTagName是本机的,而且速度很快)。

    所以如果我们可以依赖.copy按钮作为输入标记:

    $('#registration-information input.copy-button')
    

    或者我们可以依赖它作为一个输入或锚定标记

    $('#registration-information input.copy-button, #registration-information a.copy-button')
    

    如果注册信息中有大量的HTML元素,那么在ies6和ies7中这些选项可能会更快。我尝试为所有可能保持这种状态的唯一容器提供id,这样我就可以随时使用id来更有效地使用JQuery选择器。

    $('.copy-button')
    

    如果足够的话,即使在一个大的html文档上,也会扼杀ie6。如果您计划多次使用选择器的结果,请将其保存到var中。它非常简洁,在某些情况下很容易忘记这些操作可能是相当资源密集型的操作。