【问题标题】:Improving JavaScript code in a view file改进视图文件中的 JavaScript 代码
【发布时间】:2011-07-06 22:15:44
【问题描述】:

我正在使用 Ruby on Rails 3.0.7,我想知道如何重构DRY(不要重复自己)和改进 我的视图文件中的以下代码:

<% articles.each do |article| %>

  <div>
    <%= link_to 'add', '#', :id => "create_#{article.id}" %>
  </div>

  <script type="text/javascript">
    # Code - Block 1
    $jQ('#create_<%= article.id %>').live('click', function(event) {
      $jQ.ajax({
        type:    "POST",
        url:     "<%= article_url(@article) %>/create",
        data:    "article_id=<%= @article.id %>",
        error:   function(jqXHR, textStatus, errorThrown) {
          alert(textStatus + ' - ' + errorThrown + '\n\n' + jqXHR.responseText);
        },
        success: function(data, textStatus, jqXHR) {
          $jQ('#create_<%= article.id %>').replaceWith('<%= escape_javascript("added") + (link_to 'remove', '#', :id => "destroy_#{article.id}") %>')
        }
      });
    });

    # Code - Block 2
    $jQ('#destroy_<%= .id %>').live('click', function(event) {
      $jQ.ajax({
        type:    "POST",
        url:     "<%= article_url(@article) %>/destroy",
        data:    "article_id=<%= @article.id %>,
        error:   function(jqXHR, textStatus, errorThrown) {
          alert(textStatus + ' - ' + errorThrown + '\n\n' + jqXHR.responseText);
        },
        success: function(data, textStatus, jqXHR) {
          $jQ('#destroy_<%= article.id %>').replaceWith('<%= escape_javascript("removed") + (link_to 'add', '#', :id => "create_#{article.id}") %>')
        }
      });
    });
  </script>

<% end %>

注意

  • each 声明!
  • 上面的“两个代码块”几乎相等。

【问题讨论】:

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


    【解决方案1】:
    • 将主体放在一个字符串中
    • 有一个数组用于两次迭代(一个使用['create','added','remove',destroy'],另一个使用['destroy','removed','add','create']
    • 循环两次 (0..1),为找到文本的槽插入数组值
      • 第一关:array[0][0], array[0][0], array[0][0], array[0][1], array[0][2], array[0][3]
      • 第二遍:array[1][0], array[1][0], array[1][0], array[1][1], array[1][2], array[1][3]

    注意:我的 Ruby 生锈了,所以这里是伪代码。
    示例(查找ary[i][n]):

    ary = [['create','added','remove',destroy'],
           ['destroy','removed','add','create']]
    
    for i in (0..1)
       $jQ('#**ary[i][0]_<%= article.id %>').live('click', function(event) {
          $jQ.ajax({
             type:    "POST",
             url:     "<%= article_url(@article) %>/ary[i][0]",
             data:    "article_id=<%= @article.id %>",
             error:   function(jqXHR, textStatus, errorThrown) {
                         alert(textStatus + ' - ' + errorThrown + '\n\n' + jqXHR.responseText);
                      },
             success: function(data, textStatus, jqXHR) {
                         $jQ('#ary[i][0]_<%= article.id %>')
                            .replaceWith('<%= escape_javascript("ary[i][1]") + (link_to 'ary[i][2]', '#', :id => "ary[i][3]_#{article.id}") %>')
                      }
          });
       });
    end
    

    【讨论】:

    • 我完全不明白你的做法(可能是因为我是新手)。 'array[0][0], array[0][0], array[0][0], ...' 和 'array[1][0], array[1][0] 是什么意思],数组[1][0],...'?我应该如何“循环”数组[loopCountVar]?
    • 我的意思是,您将在字符串中调用第一个数组元素三次。我不记得有任何 Ruby,所以我不打算提供示例代码,但我发现我的陈述令人困惑,所以我放了一些伪代码。
    • 您可以将上述内容放在for i in (0..1)...end 之类的内容中。我已经编辑了上面的代码来演示。注意:循环和数组将是 Ruby 代码 - 我会让你弄清楚插值是如何进行的。
    【解决方案2】:

    您可以做的是在您的文章循环中嵌套另一个方法数组,并使用它来相应地调整每个方法的内部代码块。

    这是一个例子:(未经测试,但应该很接近)

    <% articles.each do |article| %>
    
      <div>
        <%= link_to 'add', '#', :id => "create_#{article.id}" %>
      </div>
    
      <script type="text/javascript">
        <% [:create,:destroy].each do |method| %>
              $jQ('#<%="#{method}_#{article.id}" %>').live('click', function(event) {
                $jQ.ajax({.   
                  type:    "POST",
                  url:     "<%= "#{article_url(@article)}/#{method}" %>",
                  data:    "article_id=<%= @article.id %>",
                  error:   function(jqXHR, textStatus, errorThrown) {
                    alert(textStatus + ' - ' + errorThrown + '\n\n' + jqXHR.responseText);
                  },
                  success: function(data, textStatus, jqXHR) {
                    $jQ('#<%="#{method}_#{article.id}" %>').replaceWith('<%= escape_javascript({'create'=>'added','destroy'=>'removed'}[method]) + (link_to( {'create'=>'add','destroy'=>'remove'}[method], '#', :id => "#{method}_#{article.id}")) %>')
                  }
                });
              });
    
        <% end %>
      </script>
    <% end %>
    

    您的其他选择是将其转换为一个辅助方法,该方法接受一篇文章和一个方法并生成正确的输出,或者您可以将必要的数据放在 html 标记中并让 javascript 转换它。

    【讨论】:

    • 我想我会用 [[:create, 'added'], [:destroy, 'removed']].each do |method, message| 循环,只是为了将定义都放在一个地方。
    • 以上是我想说的。要带走的是,是的,您正在复制您的代码,但您可能会发现复制是必要的,因为这两个事件可能会变得非常不同,带有回调和其他东西 - 请记住这一点.虽然减少线条很好,但并不总是有益的。循环也需要更多的处理(时间)。
    猜你喜欢
    • 1970-01-01
    • 2019-01-21
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多