在函数上调用函数 - Jquery

时间:2014-09-23 09:05:43

标签: javascript jquery function coffeescript

我编写了一个javascript文件:

$(function() {
  return $(".ajax-form").on("ajax:success", function(e, data, status, xhr) {
    var model_name;
    model_name = $(this).data('model-name');
    console.log('ajax form success');
    if (model_name === 'contact') {
      return $('#modal-alert-contact').modal('show');
    } else {
      return $('#modal-alert-demo').modal('show');
    }
  }).bind("ajax:error", function(e, xhr, status, error) {
    var elm, messages, model_name;
    model_name = $(this).data('model-name');
    console.log('ajax form error');
    console.log(model_name);
    if (model_name === 'contact') {
      if (xhr.responseJSON["email"]) {
        elm = $('.alert-contact-fields');
        messages = [];
        $.each(xhr.responseJSON, function(id, error_messages) {
          return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
        });
        elm.find('.messages').html(messages);
        return elm.removeClass('hide');
      } else {
        elm = $('.alert-contact-fields');
        return elm.addClass('hide');
      }
    } else {
      if (xhr.responseJSON["company_name"]) {
        elm = $('.alert-demo-fields');
        messages = [];
        $.each(xhr.responseJSON, function(id, error_messages) {
          return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
        });
        elm.find('.messages').html(messages);
        return elm.removeClass('hide');
      } else {
        elm = $('.alert-demo-fields');
        return elm.addClass('hide');
      }
    }
  });
});

我发现它很乱,并重复相同的代码。 我想做的就是这部分:

        messages = [];
        $.each(xhr.responseJSON, function(id, error_messages) {
          return messages.push(("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " "));
        });
        elm.find('.messages').html(messages);
        return elm.removeClass('hide');

我希望那部分成为一个函数,在我这样做之后,我将调用该函数在我的函数上使用它。是否有可能或者有一些技术来改进我的编码结构?

谢谢!

1 个答案:

答案 0 :(得分:2)

我想你想要这样的东西:

$(function() {
    var myform = $(".ajax-form");

    var makeMessages = function(json) {
        return $.map(json, function(error_messages, id) {
            return ("<li><strong class='titleize'>" + id + "</strong> - can't be blank</li>").replace(/_/g, " ");
        });
    };

    myform.on('ajax:success', function(e, data, status, xhr) {
        var modal_to_show = ($(this).data('model-name') === 'contact') ? '#modal-alert-contact' : '#modal-alet-demo';
        return $(modal_to_show).modal('show');
    });

    myform.on('ajax:error', function(e, xhr, status, error) {
        var fields;
        if ($(this).data('model-name') === 'contact') {
            fields = $('.alert-contact-fields');
            if (xhr.responseJSON["email"]) {
                return fields.find('messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
            }
            return fields.addClass('hide');
        } 

        fields = $('.alert-demo-fields');
        if (xhr.responseJSON["company_name"]) {
            return fields.find('.messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
        }
        return fields.addClass('hide');
    });
});

makeMessages是一个接受json对象并返回一组字符串的函数; map()是比每个()更好的函数,因为它不需要中间数组来保存值。

'success'处理程序显示了'三元运算符'的使用,也称为条件表达式。你想知道要显示哪个模态:这是你如何选择它,然后只有一个'show'操作。它更容易调试。

对于'error'处理程序,每次设置消息时,只需使用JSON调用makeMessages()并获取所需的字符串数组。因为您必须在alert - * - fields中找到messages字段,所以我调用end()将当前jquery上下文返回一次搜索(从'find'到初始$()调用),然后调用'show'相反。

由于您在选定的成功操作结束时调用'return',因此根本不需要'else'语句。他们是噪音。要么你的代码做了它的事情,要么它落到下一个阶段。

你可以删除我的fields =集合操作,因为每个节目只会被调用一次,因此重复这些操作是无害的。但是这明确了你正在做的哪个地区。

如果你想疯狂地关注你正在做的事情,把所有的决策都放在首位(要做什么,要展示什么),并使其余的代码纯机器,'如何'部分代码。 '错误'处理程序变为:

    myform.on('ajax:error', function(e, xhr, status, error) {
        var handler = (($(this).data('model-name') === 'contact') ? 
                       { 'fieldclass': '.alert-contact-fields', 'objname': 'email' } :
                       { 'fieldclass': '.alert-demo-fields', 'objname': 'company_name' });

        var fields = $(handler.fieldclass);
        if (xhr.responseJSON[handler.objname]) {
            return fields.find('.messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
        }
        return fields.addClass('hide');
    });

此时'makeMessages()'变成了一个漂亮,方便的函数,因为它显示了(和名称!好名字对维护很重要)你正在用JSON对象做什么。

一个(好的,两个)最后的替代方案:

    myform.on('ajax:error', function(e, xhr, status, error) {
        var drawResults = function(fieldclass, objname) {
            var fields = $(fieldclass);
            if (xhr.responseJSON[objname]) {
                return fields.find('messages').html(makeMessages(xhr.responseJSON)).end().removeClass('hide');
            }
            return fields.addClass('hide');
        };

        return ($(this).data('model-name') === 'contact' ?
                drawResults('.alert-contact-fields', 'email') :
                drawResults('.alert-data-fields', 'company_name'));

        /* Absolutely minimal alternative, but some people find
         * using the apply method obfuscating. */

        return drawResults.apply(this, $(this).data('model-name') === 'contact' ?
                                 ['.alert-contact-fields', 'email'] :
                                 ['.alert-data-fields', 'company_name']);
    });

不是预先使用字段和决策,而是将所有决策制定在最后,并描述一旦做出决定后会发生什么。这使用了更熟悉的调用函数的语法。重要的是要看到drawResults()已经可以访问xhr对象,因此没有必要将其传入。

最后一个可能的提取是将$(this).data('model-name') === 'contact'转换为函数,例如isDemo(),这样代码只会发生一次并且名称也很好。