Rails 3.1的JavaScript资产管道

5

好的,我已经阅读了很多关于Rails 3.1新资产管道的信息,但是我没有找到一个适当的答案来解决我的疑问。

我根据我正在渲染的视图#动作来按需加载我的.js文件。我这样做是为了防止错误的绑定并加载小的.js文件。

candidate_opportunities#index

$(".sortable_drag_n_drop").sortable({
    update: function(event, ui) {
        $.post('/candidate_opportunities/sort', $(this).sortable('serialize'));
    },
    handle: 'span'
});

candidate_companies#index

$(".sortable_drag_n_drop").sortable({
    update: function(event, ui) {
        $.post('/candidate_companies/sort', $(this).sortable('serialize'));
    },
    handle: 'span'
});
$(".sortable_drag_n_drop").disableSelection();

现在什么是最好的解决方案?

  • 我应该更改我的绑定,并让Sprockets使用//= require_tree .编译所有的.js文件吗?
  • 还是应该根据我的视图来加载.js,这样我就不会得到一个巨大的application.js
2个回答

6
如果您要将它更新到管道,您有几个选项。在决定时,您应该考虑管道应该如何工作。
总的来说,管道的目的是将所有JS合并到一个文件中并进行缩小/压缩。这样做的目的是减少每页请求的数量,并允许设置远期标头,以便资源在浏览器或透明代理/缓存中缓存。
接下来是一些选项。
1. 与现在相同。
您可以像现在一样继续进行。我假设您正在使用rails帮助程序将这些视图JS文件添加到主布局文件中。 您可以在管道中保持相同,但是必须将所有使用的文件添加到预编译数组中:
config.assets.precompile + = ['candidate_opportunities.js', 'candidate_companies']
资产必须在assets / javascripts中,但是无需将它们添加到清单文件中,因为您在单独添加每个文件。
强烈建议您坚持使用Rails默认值进行管道和生产资产的预编译。
缺点是在这些页面上会增加额外的请求,但是只有在应用程序处于高负载下时才会出现此问题。
2. Asset Pipeline Way(TM)
要在管道中执行此操作,您需要将这些文件移动到assets / javascripts中,并像您所说的那样require_tree。
在您的情况下,JS片段针对相同的类(但具有不同的后缀URL),因此这将无法工作。 并且使用require_tree,文件的顺序可能不是您想要的。
一个新的3.1应用程序为视图生成文件(我想),但是期望它们将针对标记中唯一的属性(从站点角度)进行目标,因为所有文件都包含在application.js中。
为了避免JS冲突的问题。 我建议您重构JS片段,使其更通用。 您可以在可排序对象上使用data-post-url属性:
<ul class="sortable_drag_n_drop" data-post-url="/candidate_opportunities/sort">
然后在JS中收集url。
这不仅更DRY,而且您拥有更少的总体JS,并且可以完全使用预期的管道。

(2) 正是我所做的。我们难道不都喜欢数据属性吗? :) - Frexuz

0

我对Rails资产管道感到沮丧。也许不是整个资产管道的问题,而是Rails组织JavaScript的方式真的不太合理。

目前,Rails每个控制器都有一个单独的JavaScript文件。从逻辑组织的角度来看,这在某种程度上是好的。但是,资产管道将所有这些文件压缩成一个大的js文件。因此,你的js文件虽然组织得很好,但它们会一次性加载,导致变量冲突、函数冲突、其他代码冲突和其他意外行为。因为作为开发人员,我们真正想要的是一种简单的方法来执行或加载特定于页面的JavaScript。

一个著名的方法是只包含每个页面的特定JavaScript文件。是的,这样做可以起作用,但如果我们请求每个页面的不同JavaScript文件,就无法使用资产管道提供的性能提升。

我的解决方案是创建一个JavaScript对象,保存所有特定于页面的函数,然后在Rails执行匹配的控制器操作对时获取并执行它们。像这样:

PageJs = {};
PageJs["users/new"] = function(){ 
  alert("I will be called when users/new action is executed");
};

基本上,那就是核心思想。我已经实现了这个想法,并为此创建了一个 gem。请查看 Paloma,了解如何在不复杂设置的情况下逻辑地组织 js 文件并执行特定于页面的 javascript。
以下是关于如何使用 Paloma 的示例:
Javascript 文件:
Paloma.callbacks['users/new'] = function(params){
  // This will only run after executing users/new action
  alert('Hello New Sexy User');
};

Rails 控制器:

def UsersController < ApplicationController
  def new
    @user = User.new
    # No special function to call, 
    # the javascript callback will be executed automatically
  end
end

这只是一个快速的示例,但它有更多的功能,我相信它可以轻松解决您的问题。

谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接