【问题标题】:jQuery Refactoring - DRYjQuery 重构 - DRY
【发布时间】:2015-06-13 03:23:21
【问题描述】:

我有这两个函数,在我的主要函数中。正如您将看到的,它们两者之间的唯一区别在于它们如何附加/编辑 html。我想提出两个新功能会很好,一个用于前半部分,另一个用于下半部分。我不确定这是否可以使用 jQuery,甚至使用 JavaScript,因为我不知道如何在这些函数中调用这些新函数,如果这有意义的话。任何帮助/指导都会很棒!

这是第一个

$('#save').click(function(){
var title = $('#title').val();
var tags = $('#tags').val();
var notes = $('#notes').val();
var myDate = new Date();
if (title.length < 1) {
  $('.title-warn').show();
}
if (tags.length < 1) {
  $('.tags-warn').show();
}
if (notes.length < 1) {
  $('.notes-warn').show();
}
if (title.length >= 1 && tags.length >= 1 && notes.length >= 1) {
  $allNotes.prepend('<li class="note"><div><h1>' + title + '</h1><div class="date">      <h2>'+ myDate.toDateString() +'</h2><span class="btn btn-edit">Edit</span></div><h3>' + tags + '</h3><p>' + notes + '</p></div></li>');
  $allNotes.show();
  $newNote.hide();
  $('.title-warn').hide();
  $('.tags-warn').hide();
  $('.notes-warn').hide();
}
$('#title').val('');
$('#tags').val('');
$('#notes').val('');
$('#search').prop('disabled', false);
$('#search').attr("placeholder", "Search by title, tags, date, or even words/sentences in notes");
$('.btn-search').prop('disabled', false);
});

现在是第二个

$('#edit').click(function(){
var title = $('#edit-title').val();
var tags = $('#edit-tags').val();
var notes = $('#edit-notes').val();
var myDate = new Date();
if (title.length < 1) {
  $('.title-warn').show();
}
if (tags.length < 1) {
  $('.tags-warn').show();
}
if (notes.length < 1) {
  $('.notes-warn').show();
}
if (title.length >= 1 && tags.length >= 1 && notes.length >= 1) {
  $('.edited-note').html('<div><h1>' + title + '</h1><div class="date">      <h2>'+ myDate.toDateString() +'</h2><span class="btn btn-edit">Edit</span></div><h3>' + tags + '</h3><p>' + notes + '</p></div>');
  $('.allnotes').show();
  $('.edit-note').hide();
  $('.title-warn').hide();
  $('.tags-warn').hide();
  $('.notes-warn').hide();
}
$('#title').val('');
$('#tags').val('');
$('#notes').val('');
$('#search').prop('disabled', false);
$('#search').attr("placeholder", "Search by title, tags, date, or even words/sentences in notes");
$('.btn-search').prop('disabled', false);
$('.edited-note').removeClass('edited-note');
});

当然,如果有人对我的代码的任何其他方面有任何建议,我会接受批评!

【问题讨论】:

  • 你能稍微澄清一下你所说的下半场是什么意思吗?此外,在多个选择器上执行相同操作时,您可以通过一次全部选择它们来节省资源和输入:$('.title-warn, .tags-warn, .notes-warn').hide(); 如果您喜欢冒险,您可以实施这个小技巧。 ;)
  • 我只是指我添加/编辑 html 之后的部分。不过,我一定会采纳你的把戏,谢谢!

标签: javascript jquery refactoring dry


【解决方案1】:

您回答了自己的问题! “正如您将看到的那样,它们两者之间的唯一区别在于它们如何附加/编辑 html。”最初相当天真和机械的重构尝试可能看起来像这样,只是将所有公共代码提取到共享函数中:

function preHandler(title, tags, notes) {
    if (title.length < 1) {
        $('.title-warn').show();
    }
    if (tags.length < 1) {
        $('.tags-warn').show();
    }
    if (notes.length < 1) {
        $('.notes-warn').show();
    }

    return title.length >= 1 && tags.length >= 1 && notes.length >= 1;

}


function commonPost () {

    $('#title').val('');
    $('#tags').val('');
    $('#notes').val('');
    $('#search').prop('disabled', false);
    $('#search').attr("placeholder", "Search by title, tags, date, or even words/sentences in notes");
    $('.btn-search').prop('disabled', false);


}



$('#save').click(function(){
    var title = $('#title').val();
    var tags = $('#tags').val();
    var notes = $('#notes').val();
    var myDate = new Date();
    if  (preHandler(title, tags, notes)) {

        $allNotes.prepend('<li class="note"><div><h1>' + title + '</h1><div class="date">      <h2>'+ myDate.toDateString() +'</h2><span class="btn btn-edit">Edit</span></div><h3>' + tags + '</h3><p>' + notes + '</p></div></li>');
        $allNotes.show();
        $newNote.hide();
        $('.title-warn').hide();
        $('.tags-warn').hide();
        $('.notes-warn').hide();

    }
    commonPost();

});


$('#edit').click(function() {
    var title = $('#edit-title').val();
    var tags = $('#edit-tags').val();
    var notes = $('#edit-notes').val();
    var myDate = new Date();

    if  (preHandler(title, tags, notes)) {

        $('.edited-note').html('<div><h1>' + title + '</h1><div class="date">      <h2>'+ myDate.toDateString() +'</h2><span class="btn btn-edit">Edit</span></div><h3>' + tags + '</h3><p>' + notes + '</p></div>');
        $('.allnotes').show();
        $('.edit-note').hide();
        $('.title-warn').hide();
        $('.tags-warn').hide();
        $('.notes-warn').hide();

    }

    commonPost();
    $('.edited-note').removeClass('edited-note');

});

当只有两种情况时,它并没有真正赢得你那么多。但是,如果有两个以上的人在做这种重构,就会开始收获回报。

第一次尝试可以改进(很多)。也许好人会发帖。但这将是一个很好的第一次尝试。

【讨论】:

  • 我同意。如果不是什么,第一次尝试是您应该认真考虑的最低限度。
【解决方案2】:

一般来说,我喜欢创建某种控制器类,它为我的应用程序中的每个页面执行所有 UI 工作。这使测试变得更加容易,因为您可以以非常简单的方式调用目标方法。

我也喜欢将我的选择器隐藏在易于阅读的变量后面,所以如果我要在几周/几个月后阅读这个文件,我可以通过阅读高级逻辑的意图来快速提高自己的速度去做。 (仅供参考,在我下面的回答中,我没有这样做。我实际上不知道 editTitle 应该代表什么。但这里有几个我如何将其重命名为的示例:TaskTitle、BlogTitle 等)

这些确实都是指导方针,但我希望我一直这样编写代码。我建议您抽出一些时间阅读有关 javascript 设计模式、编程习惯等方面的知识。

var myApp = new app();

$(function () {
    myApp.init();
});

var app = function () {
    var editTitle = "#edit-title";
    var editTitleWarning = ".title-warn";

    var editTags = "#edit-tags";
    var editTagsWarning = ".tags-warn";

    var editNotes = "#edit-notes";
    var editNotesWarning = ".notes-warn";

    var saveButton = "#save";
    var editButton = "#edit";

    var updateUI = function (args) {
        var isSave = args.data.isSave;
        var title = $(editTitle).val();
        var tags = $(editTags).val();
        var notes = $(editNotes).val();
        var myDate = new Date();

        // (suggestion) add comment here 
        if (title.length < 1) {
            $(editTitleWarning).show();
        }

        // (suggestion) add comment here 
        if (tags.length < 1) {
            $(editTagsWarning).show();
        }

        // (suggestion) add comment here 
        if (notes.length < 1) {
            $(editNotesWarning).show();
        }

        if (isSave) {
            // add save append code here
        } else {
            // add edit html code here
        }

        // add remaining code here
    };

    this.init = function () {
        $("body")
            .on("click", saveButton, { isSave = true }, updateUI)
            .on("click", editButton, { isSave = false }, updateUI);
    };
}

【讨论】:

    【解决方案3】:

    只谈论使代码干燥(而不是一般地正确构建它),我可能会将代码重写为:

    var handler = function(prefix, htmlHandler, removeEditedNoteCls) {
        prefix = '#' + (prefix === false ? '' : (prefix + '-'));
        var list = ['title', 'tags', 'notes'],
          i = 0,
          h = {
            date: new Date
          },
          act = true;
        for (; i < list.length; i++) {
          h[list[i]] = $(prefix + list[i]).val();
          if (h[list[i]].length < 1) {
            $('.' + list[i] + '-warn').show();
            act = false;
          }
        }
        if (act) {
          htmlHandler.call(this, h);
          for (i = 0; i < list.length; i++) {
            $('.' + list[i] + '-warn').hide();
          }
        }
        for (i = 0; i < list.length; i++) {
          $('#' + list[i]).val('');
        }
        $('#search').prop('disabled', false);
        $('#search').attr("placeholder", "Search by title, tags, date, or even words/sentences in notes");
        $('.btn-search').prop('disabled', false);
        if (removeEditedNoteCls) {
          $('.edited-note').removeClass('edited-note');
        }
      },
      prepend = function(h) {
        $allNotes.prepend('<li class="note"><div><h1>' + h.title + '</h1><div class="date">      <h2>' + h.date.toDateString() + '</h2><span class="btn btn-edit">Edit</span></div><h3>' + h.tags + '</h3><p>' + h.notes + '</p></div></li>');
        $allNotes.show();
        $newNote.hide();
      },
      replace = function(h) {
        $('.edited-note').html('<div><h1>' + h.title + '</h1><div class="date">      <h2>' + h.date.toDateString() + '</h2><span class="btn btn-edit">Edit</span></div><h3>' + h.tags + '</h3><p>' + h.notes + '</p></div>');
        $('.allnotes').show();
        $('.edit-note').hide();
      };
    $('#save').click(function() {
      handler('', prepend);
    });
    $('#edit').click(function() {
      handler('edit', replace, true);
    });

    基本上,你:

    1. 不要重复 var 每个 each 变量声明。使用逗号分隔同一 var 下的声明。虽然与 DRY 没什么大不了,但它使代码更短更好。
    2. 识别重复/相似的东西并将其压缩为:
      • 循环遍历仅包含差异的数组。在您的情况下,它将是 ID 数组 ['title', 'tags', 'notes'];或
      • 接受差异作为参数的方法。在您的情况下,“编辑”和“保存”处理程序非常相似,这应该是您将它们包装到命名方法中的第一个信号(在我的示例中为 handler)。

    【讨论】:

      猜你喜欢
      • 2016-02-20
      • 1970-01-01
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多