2010-08-09 54 views
156

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文件,或者將其保存在標題查找的實例變量中?

+0

可能使用[使用Rails 3.1,你把你的「頁面特定」JavaScript代碼?)重複(http://stackoverflow.com/questions/6167805/using-rails-3-1-where-do-you -put-your-page-specific-javascript-code) – 2013-01-11 01:24:13

+0

對於那些想要完全理解它如何工作以及哪些是最好的請閱讀http://railsapps.github.io/rails-javascript-include-external.html 。這是迄今爲止我在這個主題上看到的最好的文檔。這不僅是對Rails的一個很好的閱讀,也是對web開發人員的一個很好的閱讀。這就是爲什麼最好以軌道方式做事情的原因。我肯定會爲未來的問題使用Unholy Rails。哇。 – DutGRIFF 2014-01-22 22:22:08

+2

@KateGregory,一個更新。 – 2014-07-14 09:39:19

回答

145

我喜歡做的是在content_for :head塊中包含按視圖的Javascript,然後在您的應用程序佈局中包含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> 
+0

我喜歡它 - 謝謝! – 2010-08-11 20:24:02

+39

爲什麼不使用'<%= javascript_include_tag「my_javascipt_file」%>'? – AJP 2011-12-17 18:09:24

+5

@AJP我猜那麼它就會破壞資產管道 – lulalala 2012-03-06 06:36:10

11

我更喜歡以下...

在你的a pplication_helper.rb文件

def include_javascript (file) 
    s = " <script type=\"text/javascript\">" + render(:file => file) + "</script>" 
    content_for(:head, raw(s)) 
end 

,然後在您的特定視圖(app /視圖/書籍/在這個例子中index.html.erb)

<% include_javascript 'books/index.js' %> 

...似乎爲我工作。

9

如果你不想使用資產管道或complex work arounds來獲得必要的頁面特定的JavaScript(我同情),最簡單和最健壯的方式,其實現與上面的答案相同,但代碼少只是使用:

<%= javascript_include_tag "my_javascipt_file" %> 

注:這確實需要一個更http請求每包括標籤比如果想僅包含一個頁面上的JavaScript其使用content_for :head

+0

'javascript_include_tag'正是我一直在尋找的東西,歡呼AJP – 2012-08-31 07:12:45

+0

你在哪兒把「my_javascipt_file 「?資產/ javascripts?但是如果是這樣,那麼在application.js中不會自動用'// require。 – qix 2013-03-08 18:32:12

+0

@Linus yep,'// = require .'會將該腳本帶入您網站的任何頁面,因此您必須執行Kenny Grant(使用'// = require_tree。/ global'')或bjg建議的操作。 – AJP 2013-03-09 16:52:17

101

的答案,你可以將其包含在頁面內聯當然,但是如果你想分組你的JavaScript並利用資產管道,縮小的js等等,這是可能的,並且有額外的js資源,這些js資源通過將你的js分成只應用在某些控制器/視圖/部分網站中的組而被加載到特定頁面上。

移動你的js的資產到文件夾中,爲每個單獨的清單文件,所以如果你有一個管理員的js庫,僅在後端使用,你可以這樣做:

  • 資產
    • JavaScript的
      • 管理
        • ... JS
      • admin.js(艙單管理組)
      • 的application.js(艙單應用全局組)
      • 全球
        • ... JS

in the existing 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 

確保艙單這個新的JS通過編輯配置/ production.rb

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

然後調整頁面佈局加載,這樣就可以包括頁頭的一些額外的js:

<%= content_for :header %> 

然後在視圖中你想包括這個特定的js組(以及正常的應用程序組)和/或任何特定頁面,JS,CSS等:

<% content_for :header do %> 
    <%= javascript_include_tag 'admin' %> 
<% end %> 

當然你也可以做類似的方式CSS和組它同樣的事情只適用於某些該網站的區域。

+0

If您可以將所有清單保留在可以告訴rails的位置以預編譯該文件夾中的所有內容。這樣你只需要編輯一次production.rb,不要跟蹤你添加的內容。 – Undistraction 2012-11-13 22:51:56

+0

不知道你可以這樣做 - 所以你可以有一個「清單」文件夾,其中包含您的清單,以及個人js團體?我可能會嘗試一下。我希望他們有一個默認的稍微更理智的設置,因爲看起來他們認爲你只會把所有的js全部放入到一個大文件中。 – 2013-02-22 10:53:41

+0

奇怪的是,如果我使用'// require_tree。/ global',我得到一個Sprockets :: FileNotFound錯誤,但是如果我使用'// = require_directory。/ global'使用Rails 3.2.12則不會。 – qix 2013-03-08 18:40:30

1

好了,所以也許這就像最糟糕的工作,各地不斷,但我創造,只是呈現出一個控制器方法的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"} 

如果出於某種原因,我們不想這樣做,然後讓我知道。

3

我的理解是,資產管道旨在通過將所有js拼合成一個(縮小)文件來減少頁面加載時間。雖然表面上看起來令人反感,但它實際上是一種已經存在於C和Ruby等流行語言中的功能。諸如「包含」標籤之類的東西是爲了防止多次包含文件,並幫助程序員組織他們的代碼。當你使用C編寫和編譯程序時,所有代碼都存在於正在運行的程序的每個部分,但是隻有在使用該代碼時纔會將方法加載到內存中。從某種意義上說,編譯好的程序不包含任何內容,以保證代碼的模塊性很好。我們通過這種方式編寫程序來實現代碼模塊化,操作系統只會將給定位置所需的對象和方法加載到內存中。甚至有「特定方法包含」這樣的東西嗎?如果你的Rails應用程序很安靜,這實質上就是你所要求的。

如果您編寫JavaScript,以便增強頁面上HTML元素的行爲,那麼這些函數是按設計「頁面特定」的。如果有一些複雜的代碼以不管上下文如何執行的方式編寫,那麼可以考慮將代碼綁定到html元素(您可以使用body標籤,如Garber-Irish method中所述)。如果某個函數有條件地執行,則性能可能會小於所有這些額外的腳本標記。

我正在考慮使用paloma寶石,如rails apps project中所述。然後你就可以讓你的JavaScript頁面,具體由包括在帕洛瑪回調頁面特有的功能:

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

您使用的軌道,所以我知道你愛的寶石:)

11

這些答案對我的幫助噸!如果有人想要多一點...

  1. 如果你想讓它們預編譯,你需要將javascripts放入清單。但是,如果您需要application.js.coffee中的每個JavaScript文件,那麼每當您導航到其他頁面時,都會加載所有javacsript文件,並且執行頁面特定JavaScript的目的將被打敗。

因此,您需要創建自己的清單文件(例如speciifc.js),這將需要所有頁面特定的JavaScript文件。此外,修改require_treeapplication.js

應用程序/資產/ Java腳本/ application.js中

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

應用程序/資產/ Java腳本/ specific.js

//= require_tree ./specific 

然後在你的environments/production.rb使用config選項將此清單添加到預編譯列表中,

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中生成關聯的咖啡文件文件。有真正的控制器特定的 javascripts,只有當用戶到達特定的控制器視圖時才加載。

因此,我創建另一個清單controller-specific.js

應用程序/資產/ Javascript角/控制器specific.js

//= require_directory .

這將包括所有與控制器相關聯的自動生成的coffeescripts。另外,您需要將其添加到預編譯列表中。

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

+0

非常感謝您的詳細解答。我應該在哪裏放置'javascript_include_tag params [:controller]'。目前我的application.html.erb有這行'javascript_include_tag'應用程序''。我應該用另一條線代替嗎? – lnreddy 2013-07-22 19:18:04

+1

另外,我應該在'content_for:header'塊中放置這行'<%= javascript_include_tag「specific/whatever.js」%>'嗎? – lnreddy 2013-07-22 19:19:50

+1

對於我來說,你需要搞亂'config.assets.precompile'。 'app/assets/javascripts/*。js'中的所有內容都不是自動預編譯的嗎? – AlexChaffee 2014-08-01 16:02:01

1

添加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 %> 
2

您不應該加載您的JS或CSS文件以外的資產管道,因爲你洛杉磯發掘使Rails如此卓越的重要特性。你不需要另一個寶石。我相信儘可能少使用寶石,在這裏使用寶石不是必要的。

你想要什麼被稱爲「特定於控制器的Javascript」(「Action Specific Javascript is included at the bottom)」這允許你爲特定的控制器加載一個特定的JavaScript文件試圖將你的Javascript連接到一個View是有點......後退,並沒有遵循MVC設計模式,你想將它與你的控制器或你的控制器內的動作聯繫起來

不幸的是,無論出於何種原因,Rails開發者決定,默認情況下,加載位於資產目錄中的每個JS文件爲什麼他們決定這樣做,而不是默認啓用「Controller Specific Javascript」,我永遠不會知道,這是通過application.js文件完成的,默認情況下,該文件包含以下代碼行:

//= require_tree . 

這就是所謂的指令。這是什麼鏈輪用來加載assets/javascripts目錄中的每個JS文件。默認情況下,鏈輪自動加載application.js和application.css,require_tree指令將每個JS和Coffee文件加載到它們各自的目錄中。

注:當你的支撐架(如果你不是腳手架,現在正是入手的好時機),那麼Rails會自動生成一個咖啡文件爲你,爲的是支架的控制器。如果你想讓它產生標準JS文件,而不是一個咖啡文件,然後刪除默認啓用在的Gemfile,你的腳手架反而會創造JS文件咖啡寶石

好,所以第一步以實現「控制器特別的Javascript」是從你的application.js文件中刪除require_tree代碼或資產/ JavaScript的目錄內將其更改爲一個文件夾,如果你仍然需要全球JS文件。即:

//= require_tree ./global 

第2步:走進你的config /初始化/ assets.rb文件,並添加以下內容:

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

插入所需的控制器的名字。

第3步:在application.html.erb文件,該更換javascript_include_tag(注意PARAMS [:控制器]部分:

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

重新啓動服務器和中提琴,這是JS文件!與支架現在僅當控制器被稱爲負載產生。

需要加載一個具體行動的特定JS文件在你的控制器,IE /用品/新?難道這不是:

application.html.erb

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

配置/初始化/ assets.rb

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

然後添加一個新的文件夾具有相同的名稱,你控制器您的assets/javascripts文件夾,並將您的js文件與您的動作放在同一個名稱中。然後它會將其加載到該特定操作上。

相關問題