根据我的理解,所有的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个页面上包含相同的代码。事实上,您再也不需要在站点的任何地方包含手动脚本标记。

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


当前回答

我还没有尝试过这个方法,但看起来下面的方法是正确的:

如果你有一个content_for是javascript(例如与真正的javascript在里面),链轮将不知道它,因此这将以同样的方式工作,因为它现在。 如果你想从javascript包中排除一个文件,你可以进入config/sprockets。并相应地修改source_files文件。然后,您只需在需要的地方包括您排除的任何文件。

其他回答

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

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

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

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

这是我如何解决样式问题:(原谅Haml)

%div{:id => "#{params[:controller].parameterize} #{params[:view]}"}
    = yield

这样我开始所有特定的页面。css。Sass文件:

#post
  /* Controller specific code here */
  &#index
    /* View specific code here */
  &#new
  &#edit
  &#show

这样可以很容易地避免任何冲突。 当涉及到.js时。你可以初始化Coffee文件中的元素,比如;

$('#post > #edit') ->
  $('form > h1').css('float', 'right')

希望这能有所帮助。

我没有看到一个答案,真正把它放在一起,并为你铺开。因此,我将尝试把meleyal, sujal (la ClosureCowboy), Ryan回答的第一部分,甚至Gal关于Backbone.js的大胆陈述……以一种简短而清晰的方式把它们放在一起。谁知道呢,我甚至可能满足Marnen Laibow-Koser的要求。

例子编辑

资产javascripts / js应用程序。

//= require jquery
//= require jquery_ujs
//= require lodash.underscore.min
...

视图/布局/ application.html.erb

  ...
  </footer>

  <!-- Javascripts ================================================== -->
  <!-- Placed at the end of the document so the pages load faster -->
  <%= javascript_include_tag "application" %>
  <%= yield :javascript %>

</body>
</html>

视图/ foo / index . html . erb

...
<% content_for :javascript do %>
  <%= javascript_include_tag params[:controller] %>
<% end %>

资产javascripts / foo js。

//= require moment
//= require_tree ./foostuff

assets/javascripts/foostuff/foothis.js.coffee

alert "Hello world!"

简要描述

Remove //= require_tree . from application.js and list only the JS that each page shares. The two lines shown above in application.html.erb tell the page where to include application.js and your page-specific JS. The three lines shown above in index.html.erb tells your view to look for some page-specific JS and include it at a named yield region called ":javascript" (or whatever you want to name it). In this example, the controller is "foo" so Rails will attempt to include "foo.js" at the :javascript yield region in the application layout. List your page-specific JS in foo.js (or whatever the controller is named). List common libraries, a tree, directories, whatever. Keep your custom page-specific JS someplace where you can easily reference it apart from your other custom JS. In this example, foo.js requires the foostuff tree so put your custom JS there, such as foothis.js.coffee. There are no hard rules here. Feel free to move things around and perhaps even create multiple yield regions of various names in various layouts if needed. This just shows one possible first step forward. (I don't do it exactly like this given our use of Backbone.js. I might also choose to drop foo.js down into a folder called foo instead of foostuff but haven't decided that yet.)

笔记

你可以用CSS和<%= stylesheet_link_tag params[:controller] %>做类似的事情,但这超出了问题的范围。

如果我在这里错过了一个明显的最佳实践,给我发个便条,我会考虑适应。Rails对我来说相当新鲜,老实说,到目前为止,我对它默认给企业开发带来的混乱以及普通Rails程序产生的所有流量并没有太大印象。

对于特定页面的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-*属性时)

我希望这对你有所帮助。

虽然你在这里有几个答案,我认为你的编辑可能是最好的选择。我们在团队中使用的一个设计模式是从Gitlab获得的,它就是Dispatcher模式。它的功能与您正在讨论的类似,但是页面名称是由rails在body标记中设置的。例如,在你的布局文件中,只包括(在HAML中):

%body{'data-page' => "#{controller}:#{action}" }

然后在javascripts文件夹中的dispatcher.js.coffee文件中只有一个闭包和一个switch语句,如下所示:

$ ->
  new Dispatcher()

class Dispatcher
  constructor: ->
    page = $('body').attr('data-page')
    switch page
      when 'products:index'
        new Products() 
      when 'users:login'
        new Login()

在单个文件(例如products.js.coffee或login.js.coffee)中,你所需要做的就是将它们封装在一个类中,然后将类符号全球化,这样你就可以在调度程序中访问它:

class Products
  constructor: ->
    #do stuff
@Products = Products

Gitlab有几个这样的例子,如果你好奇的话,你可能想要戳一下:)