【问题标题】:Improve unobtrusive javascript (and possibly use CoffeeScript) in a Rails application在 Rails 应用程序中改进不显眼的 javascript(并可能使用 CoffeeScript)
【发布时间】:2011-03-14 14:23:20
【问题描述】:

我有一个应用程序,它使用一些 Javascript 来处理基本的 Ajax 请求,例如自动完成和实时搜索。例如,我通过以下方式实现了实时搜索;我发现了一些潜在的问题,想和你谈谈,以便有更好的代码。

app/controllers/company_controller.rb

def livesearch
  @companies = Company.search(params[:query])
  render :partial => "companies", :locals => {:companies => @companies}
end

app/views/companies/_companies.html.haml

- if companies.empty?
  None
- else
  %table#company_list
    %tr
      %th Name
      %th Description
      %th Products
      %th
    = render companies

app/views/companies/_livesearch_box.html.haml

= content_for :scripts, "jlivesearch companies"
= form_tag "#", :autocomplete => :off, :remote => true do
  %span.light
    Search:  
  = text_field_tag :search
  :javascript
    $('#search').livesearch({
      searchCallback: update_listed_companies,
      queryDelay: 200,
      innerText: "Search companies"
    });

public/javascripts/companies.js

function update_listed_companies(query) {
  if(typeof query == "undefined")
    query = "";

  $("#company_list_container").showWith(
    "/companies/livesearch?query=" + query,
    false
  );
}

public/javascripts/application.js

(function($) {
  $.fn.showWith = function (what, popup) {
    element = this;
    $.get(what, function(data) {
      element.html(data);
      if(popup)
        element.bPopup();
    });
    return element;
  };
})(jQuery);

以下是让我怀疑我的代码是否最优的事情:

  • 我在_livesearch_box.html.haml 中有Javascript 代码。
  • 即使我把它放在public/javascripts/companies_livesearch.js 中,我也必须对其中的#search 部分进行硬编码。
  • 我在public/javascripts/companies.js 中硬编码了#company_list_container(这是呈现_companies.html.haml 的div)。
  • 我在public/javascript/companies.js 中硬编码了路径/companies/liveseach?query=
  • 我没有使用 CoffeeScript,主要是因为它希望(至少如果您使用 Barista)在某处(例如在 app/coffeescripts/ 中)找到纯 JavaScript 代码并在 public/javascripts 中编译它。但在我的应用程序中,我的app/views/companies 中也有一些.js.erb 文件;例如,我有一个投票系统,它在 app/views/companies/_vote.js.erb$("#vote_link_<%= escape_javascript(@company.id.to_s) %>").html("<%= escape_javascript(vote_link_for(@company)) %>") 用 Ajax 请求将“投票这家公司”链接替换为“取消投票这家公司”链接(反之亦然),并由控制器中的 voteunvote 操作呈现。 我知道有 coffee-haml-filter 可以在 haml 文件中编译 CoffeeScript,但这不是我真正需要的,通常被弃用并被视为脏东西(?)。

所以问题至少是:

  • 如何在我的app/views/*/*.js.* 中添加 CoffeeScript?
  • 我应该有app/views/*/*.js.* 文件吗?
  • 如何以最有效和最优雅的方式删除所有这些元素 ID 和在 javascript 中硬编码的路径?

抱歉,问题太长了,感谢您结束它!

【问题讨论】:

    标签: javascript ruby-on-rails dry unobtrusive-javascript coffeescript


    【解决方案1】:

    路线

    有一些解决方案,如 js-routes(我的 fork),它允许您在 JS/CS 中编写 Router.post_path(3)。这样您就可以绕过硬编码网址。

    混合 JS 和 ERB

    我建议您避免混合使用 JS 和 Ruby。在大多数情况下,你可以通过重构你的 JS 代码来解决这个问题,结果会更容易阅读,并且可以简单地移动到一个纯 JS/CS 文件中。

    # based on your vote-link example and assuming that your link
    # looks like:
    #
    # %a(href="#"){:"data-company-id" => @company.id} Vote
    # => <a href="#" data-company-id="6">Vote</a>
    
    makeAllCompaniesVotable: () ->
      $('.company a.voteLink').click ->
        companyId = $(this).data('company-id')
        $.ajax
          url: Router.vote_company_path(companyId)
          # ...
    

    除非你使用邪恶的 eval-magic,否则你甚至不需要escape_javascript。但是您必须从部分内部删除 JavaScript。 jquery.livequery 使过渡更容易。

    $(`.company`).livequery ->
      # do something with $(this)
    

    将在每次将.company 插入文档时调用。

    硬编码 DOM 路径

    如果您正在为特定的 dom 树(或特定视图)编写代码,我不会认为这是一种不好的做法。编写不显眼的 JS 就像编写 CSS - 我们也在 CSS 中硬编码 #company_list_container,不是吗?

    $("#vote_link_<%= escape_javascript(@company.id.to_s) %>") # this is ugly though
    

    从前端调用JS代码

    为了在静态 CoffeeScript 文件和视图之间建立接口,我倾向于编写如下内容:

    :javascript
      $(function(){Companies.index()});
      $(function(){Application.globalEnhancements()});
    

    在我的观点结束时。然后,这将调用我用 CoffeeScript 编写的函数,然后使用所有需要的脚本来增强站点。可能有更好的方法(比如为 JavaScript 使用类似 Rails 的路由器 - 请参阅 Backbone.js),但它很简单并且适合我。

    如果我经常需要一些数据(例如:current_user):

    :javascript
      window.current_user = #{current_user.to_json};
    

    但是我认为没有一种高效的重构方式。我必须进行大量重构才能消除我的 ERB/JS 混乱。不过还是值得的。

    【讨论】:

      猜你喜欢
      • 2012-01-06
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 2014-04-21
      • 2014-08-08
      • 2011-03-31
      • 2011-06-12
      • 1970-01-01
      相关资源
      最近更新 更多