在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 …
- pipe理
- JavaScript的
在现有的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' %>
…似乎为我工作。
这些答案帮了我很多! 如果有人想多一点…
- 如果你想让它们预编译,你需要将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 %>