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

Rails3有一些很酷的 Unobtrusive 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 文件,还是把它放在页眉所寻找的实例变量中?

86371 次浏览

我喜欢做的是将每个视图的 Javascript 包含在 content_for :head块中,然后在应用程序布局中将 yield包含到该块中。比如说

如果它很短,那么:

<% 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>

我更喜欢下面这些。

在 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' %>

似乎对我有用。

如果你不想使用资产管道或者 复杂的工作环境来获得必要的页面特定的 javascript (我同情这一点) ,最简单和最健壮的方法就是使用:

<%= javascript_include_tag "my_javascipt_file" %>

注意: 这确实需要每个 include 标记比使用 content_for :head的答案多一个 http 请求

如果你只想在一个页面上包含 javascript,你当然可以把它包含在页面内联中,但是如果你想把你的 javascript 分组,并且利用资产管道,缩小 js 等等,这是可能的,并且有额外的 js 资产,这些资产被合并并且只加载在特定的页面上,通过把你的 js 分成只适用于站点的某些控制器/视图/部分的组。

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

  • 资产
    • Javascript
      • 管理员
        • ... Js
      • Js (管理组的清单)
      • Js (app global group 的清单)
      • 全球性的
        • ... 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 来做同样的事情,并以类似的方式将其分组,以便只应用于站点的某些区域。

好的,也许这是最糟糕的工作,但是我创建了一个控制器方法。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 混合到一个(缩小的)文件中来减少页面加载时间。虽然这在表面上看起来可能令人厌恶,但实际上它是一个已经存在于 C 和 Ruby 等流行语言中的特性。诸如“ include”标签之类的东西是为了防止多重包含一个文件,并帮助程序员组织他们的代码。当你用 C 编写和编译一个程序时,所有这些代码都会出现在你正在运行的程序的每一个部分中,但是只有当这些代码被使用时,方法才会被加载到内存中。在某种意义上,编译后的程序不包含任何东西来保证代码是很好的模块化的。我们通过这种方式编写程序来使代码模块化,而操作系统只在内存中加载给定位置所需的对象和方法。是否存在“特定于方法的包含”这样的东西?如果您的 Rails 应用程序是休息的,这基本上就是您所要求的。

如果你编写的 javascript 能够增强 HTML 元素在页面上的行为,那么这些函数在设计上就是“特定于页面的”。如果您编写了一些复杂的代码,不管上下文如何,它都会执行,那么可以考虑将这些代码绑定到 html 元素(您可以使用 body 标记,如 加伯-爱尔兰方法中所描述的)。如果一个函数有条件地执行,那么性能可能比所有这些额外的脚本标记都要小。

我正在考虑使用 Paloma gem,如 Rails 应用程序项目中所述。然后通过在 paloma 回调函数中包含特定于页面的函数,可以使 javascript 具有特定于页面的功能:

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

你用轨道,所以我知道你喜欢宝石:)

这些答案帮了我很大的忙! 如果有人想要更多..。

  1. 如果希望预编译 javascript,则需要将其放入清单中。但是,如果您需要 application.js.coffee中的每个 javascript 文件,那么每次您导航到不同的页面时,所有的 javascript 都将被加载,并且执行特定页面的 javascript 的目的将会失败。

因此,您需要创建自己的清单文件(例如 speciifc.js) ,它需要所有特定于页面的 javascript 文件。另外,从 application.js修改 require_tree

App/asset/javascript/application.js

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

App/asset/javascript/specic.js

//= require_tree ./specific

然后在 environments/production.rb中,使用配置选项将此清单添加到预编译列表中,

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

成交!所有应该总是加载的 分享 javascript 将放置在 app/assets/javascripts/global文件夹中,页面特定的 javascript 放置在 app/assets/javascripts/specific中。您可以简单地从视图中调用特定于页面的 javascript,如

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

这已经足够了,但是我还想利用 javascript_include_tag params[:controller]。当您创建控制器时,与前面提到的其他人一样,在 app/assets/javascripts中会生成一个相关的咖啡脚本文件。有真正的 特定控制器 javascript,只有当用户到达特定的控制器视图时才加载它们。

所以我创建了另一个货单 controller-specific.js

App/asset/javascript/控制器特定的. js

//= require_directory .

这将包括与控制器关联的所有自动生成的咖啡脚本。

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

看看 Pluggable _ js 可插入的 _ js gem,你会发现这个解决方案更容易使用。

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

Show.html.erb:

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

Layouts/application.html. erb

<%= yield :footer_js %>

您不应该在资产管道之外加载您的 JS 或 CSS 文件,因为您失去了使 Rails 如此优秀的重要特性。你不需要另一颗宝石。我相信使用尽可能少的宝石,在这里使用宝石是没有必要的。

您需要的是“控制器特定的 Javascript”(“动作特定的 Javascript 包含在底部)。这允许您为特定的 CONTROLLER 加载特定的 JavaScript 文件。尝试将你的 Javascript 连接到一个视图是一种... ... 向后的,并且不遵循 MVC 设计模式。您希望将其与控制器或控制器内的操作关联。

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

//= require_tree .

这就是所谓的 指令。它是 sprockets 用来加载 Asset/javascript 目录中的每个 JS 文件的工具。默认情况下,sprockets 会自动加载 application.JS 和 application.css,request _ tree 指令会加载各自目录中的每个 JS 和 Coffee 文件。

注意: 当您搭建脚手架时(如果您不搭建脚手架,那么现在是开始的好时机) ,Rails 会自动为您生成一个 咖啡文件,用于搭建的控制器。如果您希望它生成 标准 JS文件而不是 咖啡文件,那么删除 Gemfile中默认启用的 咖啡宝石,脚手架将创建 JS 文件。

好的,启用“ Controller Special Javascript”的第一步 是从 application.JS 文件中删除 need _ tree 代码,或者如果仍然需要全局 JS 文件,将其更改为 asset/Javascript 目录中的一个文件夹。例如:

//= require_tree ./global

步骤2: 进入 config/initializer/assets.rb 文件,并添加以下内容:

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

插入所需的 Controller 名称。

步骤3: 将 application.html.erb 文件中的 javascript _ include _ tag 替换为以下内容(注意 params [ : controller ]部分:

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

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

需要在控制器 中的特定 ACTION 上加载特定的 JS 文件,例如 /文章/新闻:

应用程序:

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

Config/initializer/assets.rb :

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

然后在 asset/javascript 文件夹中添加一个与您的控制器同名的新文件夹,并将与您的操作同名的 js 文件放入其中。然后将它加载到该特定操作上。