【问题标题】:Javascript: refactor into frameworkJavascript:重构为框架
【发布时间】:2014-09-16 23:48:15
【问题描述】:

我的一个 Rails 视图中有一段可怕的 jQuery 代码,它监听一个看起来像这样的事件:

<% user_request_file = params[:file] == document.id.to_s %>
<% if user_request_file %>
    <script type="text/javascript">
        $(document).ready(function() {
            $("#generate_file_btn_for_<%= document.id %>").attr('disabled', 'disabled').attr("href", "#").attr('title', 'Loading file...');
            var doc_modal_<%= document.id %> = setInterval(function() {
                $.getJSON( "<%= file_xhr_document_path(document) %>", function(file) {
                    if (file.file_generated) {
                        $("#loading_for_<%= document.id %>").fadeOut( "slow");
                        $('#document_file_modal_<%= document.id %>').modal('show');
                        $("#file_url_download_link_<%= document.id %>").attr("href", file.file_url);
                        clearInterval(doc_modal_<%= document.id %>);
                    } else if (file.file_error != null) {
                        window.location.href = "<%= file_error_document_path(document) %>";
                    }
                });
            }, 2000);
        });
    </script>
<% end %>

我想用更模块化和重构友好的东西来替换它。上面的代码每两秒侦听一次发送到其服务器的请求,如果已发送,视图将使用来自该请求的信息进行响应。

Flight 已被推荐给我作为合适的替代框架,但我真的不知道如何开始重构它。任何建议甚至是其他框架的建议都会很棒。

【问题讨论】:

  • 第一步是将 JavaScript 从模板/文本替换上下文中拉出——这同样适用于移动到 Flight 或 KO 或其他任何东西——以便它可以被视为自己的/独立模块。虽然在不同的环境下,我提供了an example here。关键是 JavaScript 被隔离在相关 API 后面,并且提供了值。

标签: javascript jquery ruby-on-rails ruby-on-rails-3


【解决方案1】:

这里有一种方法可以让它变得更好

(function($) {

  // store the information we care about once
  var doc = {
    file:     '<%= j params[:file] %>'
    id:       '<%= j document.id %>',
    path: {
      xhr:    '<%= j file_xhr_document_path(document) %>',
      error:  '<%= j file_error_document_path(document) %>'
    }
  };

  // stop immediately if file !== doc.id
  if (doc.file !== doc.id) return;

  function getJSON() {
    var xhr = $.getJSON(doc.path.xhr);
    xhr.done(onSuccess);
    xhr.fail(onError);
  }

  function onSuccess(file) {
    if (!file.file_generated) return onError();
    $("#loading_for_" + doc.id).fadeOut("slow");
    $("#document_file_modal_" + doc.id).modal("show");
    $("#file_url_download_link_" + doc.id).attr("href", file.file_url);
    setTimeout(getJSON, 2000);
  }

  function onError() {
    window.location.href = doc.path.error;
  }

  function init(event) {
    $("#generate_file_btn_for_" + doc.id)
      .prop("disabled", true)
      .attr("title", "Loading file...");
    getJSON();
  }

  if (doc.id) $(document.ready(init);
})(jQuery);

说明

您会注意到的第一件事是代码更加扁平化。在最深处,这段代码有 2 级缩进。您拥有的现有代码是 4。也许这是个人喜好,但我发现更扁平的代码更容易阅读。

这段代码将所有相关的变量存储在一个小对象中,以便我们在脚本的其余部分重用。这在很大程度上清理了 JavaScript,因为它删除了大量的 erb 调用。

var doc = {
  id:  <%= j document.id %>,
  path: {
    xhr: <%= j file_xhr_document_path(document) %>,
    error: <%= j file_error_document_path(document) %>
  }
};

从这里开始,其他改进是从有效的函数中删除$(...) 调用。更好的方法是围绕getJSON 位创建一个函数包装器,并传入您将要操作的元素。将依赖项传递给可以工作的函数总是比在函数体中静态耦合它们更好。

这只是一个开始

这绝不是最干净的代码。我不知道您还有哪些其他可用的脚本/工具,但希望这能让您了解如何开始进行一些改进。

【讨论】:

  • 这是一个非常更好的解决方案(我之前没有正确阅读)。
猜你喜欢
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 2018-08-02
  • 2013-07-18
  • 1970-01-01
  • 2012-01-25
  • 2012-08-05
  • 2011-04-06
相关资源
最近更新 更多