根据我的理解,所有的JavaScript都合并到一个文件中。Rails在添加//= require_tree时默认这样做。到你的application.js manifest文件的底部。

这听起来像是一个真正的救星,但我有点担心特定于页面的JavaScript代码。这段代码是否在每一页上执行?我想要的最后一件事是当我的所有对象只在1页上需要时,为每一页实例化它们。

此外,代码是否也有可能发生冲突?

还是在页面底部放置一个小的脚本标记,只调用一个执行页面javascript代码的方法?

你不再需要require.js了吗?

谢谢

编辑:我很感激所有的答案…我认为他们并没有真正解决问题。其中一些是关于样式的,似乎没有关联……其他人只是提到javascript_include_tag…我知道这是存在的(很明显…),但Rails 3.1的前进方式似乎是将所有JavaScript打包到一个文件中,而不是在每个页面的底部加载单个JavaScript。

我能想到的最好的解决方案是用id或类将某些特性包装在div标签中。在JavaScript代码中,只需检查id或类是否在页面上,如果在,则运行与之关联的JavaScript代码。这样,如果动态元素不在页面上,JavaScript代码就不会运行——即使它包含在由Sprockets打包的庞大application.js文件中。

我上面的解决方案的好处是,如果一个搜索框包含在100个页面中的8个页面上,那么它将只在这8个页面上运行。你也不需要在网站的8个页面上包含相同的代码。事实上,您再也不需要在站点的任何地方包含手动脚本标记。

我想这就是我问题的真正答案。


当前回答

Ryguy的答案是一个很好的答案,尽管它被投票为负分。

特别是如果你使用的是Backbone JS——每个页面都有自己的Backbone视图。然后,erb文件只有一行内联javascript,用于启动正确的骨干视图类。我认为它是一行“胶水代码”,因此它的内联是可以的。这样做的好处是你可以保留你的“require_tree”,它可以让浏览器缓存所有的javascript。

在show.html。你会得到这样的东西:

<% provide :javascript do %>
  <%= javascript_include_tag do %>
    (new app.views.ProjectsView({el: 'body'})).render();
  <% end %>
<% end do %>

在你的布局文件中,你需要:

<%= yield :javascript %>

其他回答

这个问题在很久以前就被回答和接受了,但是我基于其中一些答案和我使用Rails 3+的经验提出了我自己的解决方案。

资产管道是甜蜜的。使用它。

首先,在你的application.js文件中,删除//= require_tree。

然后在你的application_controller中。Rb创建一个helper方法:

helper_method :javascript_include_view_js //Or something similar

def javascript_include_view_js
    if FileTest.exists? "app/assets/javascripts/"+params[:controller]+"/"+params[:action]+".js.erb"
        return '<script src="/assets/'+params[:controller]+'/'+params[:action]+'.js.erb" type="text/javascript"></script>'
    end
end

然后在你的application.html.erb布局文件中,在现有的javascript include中添加你的新helper,并以raw helper为前缀:

<head>
    <title>Your Application</title>
    <%= stylesheet_link_tag "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= raw javascript_include_view_js %>
</head>

瞧,现在您可以使用与rails中其他地方相同的文件结构轻松创建特定于视图的javascript。简单地把你的文件放在app/assets/:namespace/:controller/action.js.erb!

希望这能帮助到其他人!

<%= javascript_include_tag params[:controller] %>

对于特定页面的js,您可以使用Garber-Irish解决方案。

所以你的Rails javascripts文件夹对于两个控制器(cars和users)是这样的:

javascripts/
├── application.js
├── init.js
├── markup_based_js_execution
├── cars
│   ├── init .js
│   ├── index.js
│   └── ...
└── users
    └── ...

javascript是这样的:

// application.js

//= 
//= require init.js
//= require_tree cars
//= require_tree users

// init.js

SITENAME = new Object();
SITENAME.cars = new Object;
SITENAME.users = new Object;

SITENAME.common.init = function (){
  // Your js code for all pages here
}

// cars/init.js

SITENAME.cars.init = function (){
  // Your js code for the cars controller here
}

// cars/index.js

SITENAME.cars.index = function (){
  // Your js code for the index method of the cars controller
}

和markup_based_js_execution将包含用于UTIL对象的代码,在dom就绪的UTIL上。初始化执行。

别忘了把这个放到你的布局文件中:

<body data-controller="<%= controller_name %>" data-action="<%= action_name %>">

我还认为最好使用类而不是data-*属性,以获得更好的特定于页面的css。正如Jason Garber所提到的:特定于页面的CSS选择器会非常尴尬(当你使用data-*属性时)

我希望这对你有所帮助。

Paloma项目提供了一种有趣的方法来管理页面特定的javascript代码。

他们文档中的用法示例:

var UsersController = Paloma.controller('Users'); //当Rails User#new执行时执行。 UsersController.prototype.new = function(){ 警报('你好,性感用户!”); };

在Ryan的带领下,以下是我所做的

application.js.coffee

$ ->
    view_method_name = $("body").data("view") + "_onload"
    eval("#{view_method_name}()") if eval("typeof #{view_method_name} == 'function'")
    view_action_method_name = $("body").data("view") + "_"+$("body").data("action")+"_onload"
    eval("#{view_action_method_name}()") if eval("typeof #{view_action_method_name} == 'function'")

Users.js.coffee(特定于控制器的coffeescript,e。G控制器:用户,动作:仪表盘)

window.users_dashboard_onload = () ->
    alert("controller action called")
window.users_onload = () ->
    alert("controller called")

application.html.haml

%body{:data=>{:view=>controller.controller_name, :action=>controller.action_name}}