如何干掉我的jQuery代码并使其更具可读性/可维护性?

时间:2010-10-11 19:05:33

标签: javascript jquery

我开始做很多jQuery编程。我发现我的代码变得有点难以维护并且不是那么可读。我的javascript被包含在我们的Web应用程序的每个页面上,即使它只在一个页面上使用。这有利于在加载页面之前缓存javascript,但我担心意外创建具有相同名称的函数(由我团队中的其他程序员创建)。

我是javascript的新手,所以可能会有一些我缺少的基础知识。我可以将哪些技术应用于以下代码,以及将来的其他代码,以使我的jQuery代码更易于维护和读取?

<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 个答案:

答案 0 :(得分:3)

两个提示:

  • 为代码使用命名空间以避免名称冲突。当然,Javascript中没有真正的命名空间,但您可以使用对象伪造它们。

`

var MyCode=MyCode||{
        copyField:function (e){
    },
        someOtherFunction:function(){
    }
};

    $(document).ready(function(){
        MyCode.copyField(...);
    });
  • 将您的javascript代码放入一个或多个单独的文件(每个命名空间一个),并使用第三方库(如combres)将它们合并到一个文件中,缩小它们并处理正确的缓存。它节省了大量带宽,比在不同页面上分发各种javascript函数更清晰。

答案 1 :(得分:2)

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

有一个非常好的指南和模板用于编写插件here

答案 2 :(得分:0)

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

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

我总是发现这更容易阅读,然后只是一系列变量。从表面上看,它看起来像是以var开头的代码块,并在缩进返回时结束。

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

答案 3 :(得分:0)

首先......

使用像jsunit这样的东西来测试代码。

使用名称很小的方法创建小型的命名类。该类的名称将描述它的职责。该方法的名称也将描述它的职责。

重构以删除重复。

限制使用全球范围。

阅读清洁代码:敏捷软件工艺手册[平装] Robert C. Martin(编辑)

答案 4 :(得分:0)

您可以使用YUI名称空间模型, 创建顶级对象(命名空间) 让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.Namespace1.class1 =函数(){

//你的代码 } 在其他文件中 STW.namespace( “STW.namespace1.namespace2”); STW.namespace1.namespace2.class2 =函数(){

//你的代码 }

答案 5 :(得分:0)

$ .ajax parens中的东西只是一个单一的参数,就像任何基于c的函数一样。

{}是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呼叫的选项存在差异:

示例#1 - 只需将网址更改为Google

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

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

options.data.id = "newID";

对JQuery的选择器语法提出警告。直接通过ID抓取是理想的选择。在旧版本的IE(没有本机getByClassName方法,因此有更多的解释器级循环)中,仅仅按类抓取可能会非常慢。编写选择器的理想方法会缩小到最接近的父ID,如果可以显式,则将标记名称添加到后续类选择器中以进一步缩小范围(getElementsByTagName是本机和快速的)。

因此,如果我们可以依赖.copy-button作为输入标记:

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

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

$('#registration-information input.copy-button, #registration-information a.copy-button')
如果在#registration-information中有大量的HTML元素,那么在IE 6中可能会有相当快的选择,也许可能是7。我尝试将ID提供给所有可能保持这种状态的独特容器,这样我就可以使用ID来获得更高效的JQuery选择器。

但无论你做什么,都要避免这些:

$('.copy-button')

如果有足够的可用内容,那么即使是在一个较大的HTML文档上也可能会阻塞IE 6。如果您计划多次使用选择器的结果,请将其保存到var。它非常简洁,很容易忘记在某些情况下这些操作可能是资源密集型操作。