在Rails 3应用程序中添加页面特定JavaScript的最佳方法?

Rails 3有一些不显眼的JavaScript,非常酷。

但是我想知道为特定页面添加其他JavaScript的最佳方式。

例如,我可能以前做过的事情:

<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %> 

我们现在可以使它像这样的东西不显眼

 <%= f.radio_button :rating, 'positive' %> # then in some other file $('user_rating_positive').click(function() { $('some_div').show(); } 

所以我想我的问题是在哪里/如何包含该JavaScript? 我不想填充application.js文件,因为这个JavaScript只适用于这个视图。 我应该为每个页面包含一个自定义的JavaScript文件,或者将其保存在头文件的实例variables中?

我喜欢做的是在content_for :head块中包含每个查看的Javascript,然后在应用程序布局中输出到该块。 例如

如果很短,那么:

 <% content_for :head do %> <script type="text/javascript"> $(function() { $('user_rating_positve').click(function() { $('some_div').show(); } }); </script> <% end %> 

或者,如果更长,则:

 <% content_for :head do %> <script type="text/javascript"> <%= render :partial => "my_view_javascript" </script> <% end %> 

然后,在你的布局文件中

 <head> ... <%= yield :head %> </head> 

如果你想在一个页面上包含JavaScript,你可以将它包含在页面上,但是如果你想分组你的JavaScript,并利用资产pipe道,缩小的JS等,这是可能的,并有额外的js资源,这些资源是通过将您的js分成仅适用于某些控制器/视图/站点部分的组来组合的,并且仅在特定页面上加载。

将资产中的js移动到文件夹中,每个文件夹都有一个单独的清单文件,所以如果您有一个只在后端使用的admin js库,您可以这样做:

  • 资产
    • JavaScript的
      • pipe理
        • JS …
      • admin.js(pipe理员组的清单)
      • application.js(应用程序全局组清单)
      • 全球
        • JS …

在现有的application.js中

 //= require jquery //= require jquery_ujs //= require_tree ./global // requires all js files in global folder 

在一个新的admin.js清单文件中

 //= require_tree ./admin // requires all js files in admin folder 

确保通过编辑config / production.rb来加载这个新的js清单

 config.assets.precompile += %w( admin.js ) 

然后调整您的页面布局,以便您可以包含页头的一些额外的js:

 <%= content_for :header %> 

然后在你想要包含这个特定的js组(以及正常的应用程序组)和/或任何特定于页面的js,css等的视图中:

 <% content_for :header do %> <%= javascript_include_tag 'admin' %> <% end %> 

你当然可以用css做同样的事情,并以类似的方式将它分组,只应用于网站的某些区域。

我更喜欢以下…

在你的application_helper.rb文件中

 def include_javascript (file) s = " <script type=\"text/javascript\">" + render(:file => file) + "</script>" content_for(:head, raw(s)) end 

然后在你的特定视图(在这个例子中是app / views / books / index.html.erb)

 <% include_javascript 'books/index.js' %> 

…似乎为我工作。

这些答案帮了我很多! 如果有人想多一点…

  1. 如果你想让它们预编译,你需要将JavaScripts放入清单。 但是,如果你需要每个来自application.js.coffee javascript文件,那么每当你导航到不同的页面时,所有的javacsripts都会被加载,而做页面特定的javascripts的目的将被打败。

因此,您需要创build自己的清单文件(例如speciifc.js ),这将需要所有页面特定的JavaScript文件。 另外,修改application.js require_tree

应用程序/资产/ JavaScript的/ application.js中

 //= require jquery //= require jquery_ujs //= require_tree ./global 

应用程序/资产/ JavaScript的/ specific.js

 //= require_tree ./specific 

然后在您的environments/production.rb将此清单添加到带有config选项的预编译列表中,

config.assets.precompile += %w( specific.js )

完成! 所有应该始终加载的共享 JavaScript将放置在app/assets/javascripts/global文件夹中,以及app/assets/javascripts/specific的页面app/assets/javascripts/specific 。 你可以简单地从视图中调用页面特定的JavaScripts

<%= javascript_include_tag "specific/whatever.js" %> //.js是可选的。

这已经足够了,但是我也想使用javascript_include_tag params[:controller] 。 在创build控制器时,与其他人提到的app/assets/javascripts相关联的coffeescript文件会生成。 有真正的控制器特定的 JavaScript,只有当用户到达特定的控制器视图加载。

所以我创build了另一个清单controller-specific.js

应用程序/资产/ Javascriptangular/控制器specific.js

//= require_directory .

这将包括所有与控制器相关的自动生成的咖啡文本。 另外,您需要将其添加到预编译列表中。

config.assets.precompile += %w( specific.js controller-specific.js )

如果你不想使用资产pipe道或复杂的工作来获得必要的页面特定的JavaScript(我同情),最简单和最健壮的方式,达到与上面的答案相同,但代码less,只是为了使用:

 <%= javascript_include_tag "my_javascipt_file" %> 

注意:这比每个使用content_for :head的回答要求每个include标签多一个http请求

看看pluggable_js的gem。 您可能会发现这个解决scheme更易于使用。

我的理解是,资产pipe道是为了减less页面加载时间,把所有的js混合成一个(缩小的)文件。 尽pipe表面上看起来可能有点令人厌恶,但它实际上是C和Ruby等stream行语言中已经存在的function。 像“包含”标签是为了防止多个包含文件,并帮助程序员组织他们的代码。 当你使用C编写和编译程序时,所有代码都存在于正在运行的程序的每个部分,但是只有在使用该代码时才会将方法加载到内存中。 从某种意义上说,编译的程序不包含任何东西来保证代码是很好的模块化的。 我们通过编写我们的程序来实现代码的模块化,而操作系统只是把我们需要的对象和方法加载到一个给定的地方。 有甚至“方法特定的包含”这样的东西吗? 如果你的Rails应用程序是宁静的,这实质上是你要求的。

如果您编写JavaScript,以便增强页面上的HTML元素的行为,那么这些function是按devise“特定于页面”的。 如果有一些复杂的代码是以不pipe上下文的方式执行的,也许可以考虑将代码绑定到html元素(可以使用Garber-Irish方法中描述的body标签)。 如果一个函数有条件地执行,性能可能会比所有这些额外的脚本标记更小。

我正在考虑使用paloma gem,如rails应用程序项目中所述 。 然后,您可以通过在palomacallback中包含页面特定function来使您的JavaScript页面特定:

 Paloma.callbacks['users']['new'] = function(params){ // This will only run after executing users/new action alert('Hello New Sexy User'); }; 

你用铁轨,所以我知道你爱gem:)

您不应该在资产pipe道之外加载您的JS或CSS文件,因为您失去了使Rails如此卓越的重要特性。 而且你不需要另一个gem。 我相信尽可能less使用gem,在这里使用gem是不必要的。

你想要的是“控制器特定的Javascript”(“Action Specific Javascript is included on the bottom)”。这允许你为特定的控制器加载一个特定的JavaScript文件。试图将你的Javascript连接到一个View是一种..向后并且不遵循MVCdevise模式,您希望将其与您的控制器或您的控制器内部的操作相关联。

不幸的是,无论出于何种原因,Rails开发者决定,默认情况下,每个页面都会加载位于资产目录中的每个JS文件。 为什么他们决定这样做,而不是启用“控制器特定的Javascript”默认我永远不会知道。 这是通过application.js文件完成的,该文件默认包含以下代码行:

 //= require_tree . 

这被称为指令 。 这是什么sprockets用来加载assets / javascripts目录中的每个JS文件。 默认情况下,链轮自动加载application.js和application.css,而require_tree指令将每个JS和Coffee文件加载到它们各自的目录中。

注:当你脚手架(如果你不脚手架,现在是一个好时机),Rails自动为你的脚手架的控制器生成一个咖啡文件。 如果你希望它生成一个标准的JS文件,而不是一个咖啡文件,然后删除Gemfile中默认启用的咖啡gem ,而你的脚手架将创buildJS文件。

好的,所以启用“Controller Specific Javascript”的第一步是从你的application.js文件中删除require_tree代码,或者如果你仍然需要全局的JS文件,那么把它改成assets / javascripts目录下的文件夹。 IE:

 //= require_tree ./global 

第2步:进入你的config / initializers / assets.rb文件,并添加以下内容:

 %w( controllerone controllertwo controllerthree ).each do |controller| Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"] end 

插入所需的控制器名称。

第3步:用你的application.html.erb文件replacejavascript_include_tag(注意params [:controller]部分:

 <%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track': 'reload' %> 

重新启动您的服务器和中提琴! 使用脚手架生成的JS文件现在只会在调用该控制器时加载。

需要加载一个特定的JS文件在你的控制器 ,IE / articles /新 特定的行动 ? 做这个,而不是:

application.html.erb

 <%= javascript_include_tag "#{controller_name}/#{action_name}" if AppName::Application.assets.find_asset("#{controller_name}/#{action_name}") %> 

config / initializers / assets.rb

 config.assets.precompile += %w(*/*) 

然后在您的assets / javascripts文件夹中添加一个与您的控制器同名的新文件夹,并将您的js文件与您的动作放在同一个名称中。 然后,它将在该特定操作上加载它。

好吧,也许这就像是最糟糕的工作,但我创build了一个控制器方法,只是呈现了.js文件

调节器

 def get_script render :file => 'app/assessts/javascripts/' + params[:name] + '.js' end def get_page @script = '/' + params[:script_name] + '.js?body=1' render page end 

视图

 %script{:src => @script, :type => "text/javascript"} 

如果由于某种原因,我们不想这样做,那就让我知道。

添加JS的首选方法是在页脚中,所以你可以这样做:

show.html.erb:

 <% content_for :footer_js do %> This content will show up in the footer section <% end %> 

布局/ application.html.erb

 <%= yield :footer_js %>