Rails 3 uygulamasında sayfaya özgü JavaScript eklemenin en iyi yolu nedir?


159

Rails 3, oldukça havalı bazı mütevazi JavaScript'e sahiptir.

Ancak, belirli bir sayfa için ek JavaScript eklemenin en iyi yolunun ne olduğunu merak ediyordum.

Örneğin, daha önce yapmış olabilirim:

<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %>

Şimdi böyle bir şeyle mütevazi yapabiliriz

<%= f.radio_button :rating, 'positive' %>

# then in some other file
$('user_rating_positive').click(function() {
  $('some_div').show();
}

Yani sorum şu JavaScript'i nereye / nasıl ekleyeceğimi tahmin ediyorum? application.jsBu JavaScript yalnızca bu görünüm için geçerli olduğu için dosyayı doldurmak istemiyorum . Her sayfa için bir şekilde özel bir JavaScript dosyası eklemeli miyim veya başlığın aradığı örnek değişkenine yapıştırmalı mıyım?



Bunun nasıl çalıştığını ve neyin en iyi olduğunu tam olarak anlamak isteyenler için lütfen railsapps.github.io/rails-javascript-include-external.html adresini okuyun . Bu, bu konuda gördüğüm en iyi belgeler. Sadece Rails için değil, web dev uğraşan herkes için harika bir okuma. Bu yüzden raylar yolunda bir şeyler yapmak en iyisidir. Gelecek sorularım için kesinlikle Unholy Rails kullanacağım. VAY.
DutGRIFF

Yanıtlar:


153

Ne yapmak gibi bir content_for :headblok başına görünüm Javascript ve sonra yieldda uygulama düzeninde bu bloğa dahil etmektir. Örneğin

Oldukça kısa ise:

<% content_for :head do %>
  <script type="text/javascript">
    $(function() {
      $('user_rating_positve').click(function() {
        $('some_div').show();
      }
    });
  </script>
<% end %>

veya daha uzunsa:

<% content_for :head do %>
  <script type="text/javascript">
    <%= render :partial => "my_view_javascript"
  </script>
<% end %>

Ardından, düzen dosyanızda

<head>
  ...
  <%= yield :head %>
</head>

40
Neden kullanmıyorsunuz <%= javascript_include_tag "my_javascipt_file" %> ?
AJP

5
@AJP Sanırım o zaman varlık boru hattı amacını yendi
lulalala

2
@lulalala ama cevaptaki kod yine de bunu daha karışık bir şekilde yapmıyor mu?
AJP

8
@AJP daha karışık, ancak cevabınızdan daha az http isteği var.
lulalala


103

Javascript'i yalnızca bir sayfaya dahil etmek istiyorsanız, elbette satır içi sayfaya ekleyebilirsiniz, ancak javascriptinizi gruplandırmak ve varlık boru hattından, küçültülmüş js vb. js sitenizi yalnızca belirli denetleyiciler / görünümler / bölümlerde geçerli olan gruplara bölerek birleştirilen ve yalnızca belirli sayfalara yüklenen js varlıkları.

Varlıklardaki js'lerinizi klasörlere, her biri için ayrı bir bildirim dosyasıyla taşıyın, bu nedenle yalnızca arka uçta kullanılan bir yönetici js kütüphaneniz varsa, bunu yapabilirsiniz:

  • varlıklar
    • javascripts
      • yönetim
        • ... js
      • admin.js (yönetici grubu için bildirim)
      • application.js (uygulama genel grubu için bildirim)
      • global
        • ... js

varolan application.js dosyasında

//= require jquery
//= require jquery_ujs
//= require_tree ./global // requires all js files in global folder

yeni bir admin.js bildirim dosyasında

//= require_tree ./admin // requires all js files in admin folder

Config / production.rb dosyasını düzenleyerek bu yeni js bildiriminin yüklendiğinden emin olun.

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

Ardından sayfa düzeninizi, sayfa başı için bazı ekstra j'ler ekleyebileceğiniz şekilde ayarlayın:

<%= content_for :header %>   

Ardından, bu belirli js grubunu (normal uygulama grubunun yanı sıra) ve / veya sayfaya özgü js, css vb. Eklemek istediğiniz görünümlerde:

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

Elbette css ile aynı şeyi yapabilir ve sitenin yalnızca belirli alanlarına uygulamak için benzer bir şekilde gruplayabilirsiniz.


Tüm manifestolarınızı aynı yerde tutarsanız, rayların o klasördeki her şeyi önceden derlemesini söyleyebilirsiniz. Bu şekilde production.rb dosyasını yalnızca bir kez düzenlemeniz ve eklediklerinizi takip etmemeniz gerekir.
Dağılım

Bunu yapabileceğinizi bilmiyordum - bu nedenle, manifestolarınızı ve tek tek js gruplarını içeren bir 'manifests' klasörünüz olabilir mi? Bunu deneyebilirim. Keşke onlar sadece her yerde ithal büyük bir dosyaya tüm js glob varsayalım gibi varsayılan olarak biraz daha aklı başında kurulum olsaydı.
Kenny Grant

garip, eğer kullanırsam bir Sprockets :: FileNotFound hatası alıyorum //= require_tree ./global, ancak //= require_directory ./globalRails 3.2.12 kullanarak kullanmıyorum.
qix

2
Görünüşe göre birçok komut dosyası etiketi alacaksınız. Ben varlık boru hattı ile amaç sadece bir komut dosyası etiketi olduğunu düşündüm? Sadece javascripts yazmak istiyorum böylece sayfaya özgü.
Ziggy

1
Anladığımı düşünüyorum. Ek komut dosyası etiketlerinden kaçınmak, sayfa yükleme süresi açısından oldukça önemlidir.
Ziggy

12

Bu cevaplar bana bir ton yardımcı oldu! Biri biraz daha isterse ...

  1. Önceden derlenmesini istiyorsanız javascripts'i manifestlere koymanız gerekir. Bununla birlikte, her bir javascript dosyasına ihtiyacınız varsa, application.js.coffeefarklı bir sayfaya her gittiğinizde tüm javacsripts yüklenir ve sayfaya özgü javascripts yapmanın amacı yenilir.

Bu nedenle, speciifc.jssayfaya özgü tüm javascript dosyalarını gerektiren kendi manifest dosyanızı (örn. ) Oluşturmanız gerekir. Ayrıca, değiştirme require_treegelenapplication.js

Uygulamanın / varlıklar / javascripts / application.js

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

Uygulamanın / varlıklar / javascripts / specific.js

//= require_tree ./specific

Ardından environments/production.rbbu manifest'i config seçeneği ile önceden derlenmiş listeye ekleyin,

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

Bitti! Her zaman yüklenmesi gereken tüm paylaşılan javascripts app/assets/javascripts/globalklasöre yerleştirilecek ve sayfaya özel javascripts app/assets/javascripts/specific. Görünüşe göre sayfaya özgü javascripts'i

<%= javascript_include_tag "specific/whatever.js" %> //.js isteğe bağlıdır.

Bu yeterli, ama ben javascript_include_tag params[:controller]de kullanmak istedim . Denetleyiciler oluşturduğunuzda, app/assets/javascriptsbahsedilen diğer kişiler gibi ilişkili bir kahve dosyası oluşturulur . Gerçekten var kontrolör özgü kullanıcının belirli denetleyici görünümü ulaştığında sadece yüklenen javascripts.

Bu yüzden başka bir tezahür yarattım controller-specific.js

Uygulamanın / varlıklar / javascripts / kontrolör-specific.js

//= require_directory .

Bu, denetleyicilerle ilişkili otomatik olarak oluşturulan tüm kahve tanımlamalarını içerir. Ayrıca, önceden derlenmiş listeye eklemeniz gerekir.

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


Ayrıntılı cevap için çok teşekkürler. Bu çizgiyi nereye koymalıyım javascript_include_tag params[:controller]. Şu anda application.html.erb dosyamda bu satır var javascript_include_tag 'application'. Bunu diğer hatla değiştirmeli miyim?
simha

1
Ayrıca, bu satırı <%= javascript_include_tag "specific/whatever.js" %>bir content_for :headerblok içine koymalı mıyım?
simha

1
Karmakarışık olman bana garip geliyor config.assets.precompile. Her şey app/assets/javascripts/*.jsotomatik olarak önceden derlenmiyor mu?
AlexChaffee

@AlexChaffee Yalnızca otomatik olarak bulunan dosyalar application.cssve şeklindedir application.js. Diğerleri ya diğer dosyalara dahil edilmeli ya da kullanılarak listelenmelidir config.assets.precompile. Buradan daha fazlasını okuyun
Sung Cho

Bildiri bildirimi taşındı. 4.2.0 rayları çalıştırıyorum. ve bu production.rb dosyasında yorumunu bulundu: # config.assets.precompileve config.assets.versiontaşınmış için config / ilklendiriciler / assets.rb
Curt

11

Aşağıdakileri tercih ederim ...

Application_helper.rb dosyanızda

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

ve ardından kendi görünümünüzde (bu örnekte app / views / books / index.html.erb)

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

... Benim için iş gibi görünüyor.


9

Varlık boru hattını veya karmaşık çalışma ortamını kullanmak istiyorsanız, bu sayfaya özel javascript (sempati duyuyorum) elde etmek istemiyorsanız, yukarıdaki cevaplarla aynı ancak daha az kodla elde edilen en basit ve en sağlam yol kullanın:

<%= javascript_include_tag "my_javascipt_file" %>

Not: Bu, içerme etiketi başına kullanılan yanıtlardan daha fazla bir http isteği gerektirir content_for :head


javascript_include_tagtam olarak aradığım şey, şerefe AJP
Tom McKenzie

"my_javascipt_file" yerine nereye koyarsınız? Varlıklarda / javascripts? Ama eğer öyleyse, //= require .application.js'de bir ile otomatik olarak alınmaz mı?
qix

@Linus yep, //= require .bu betiği sitenizdeki herhangi bir sayfaya getirir, böylece Kenny Grant (kullan //= require_tree ./global) veya bjg önerisi gibi bir şey yapmanız gerekir .
AJP

1
Bu değiştim, benim için çok kolay bir yöntemle yapıldı //= require_tree .etmek //= require_directory .application.js ve sonra aktifleri \ javascripts bir alt dizin oluşturulur. Aşağıdaki satırı ekleyerek js'nizi önceden derlemek için config \ initializers \ asset.rb dosyasına yeni dizini eklemeniz gerektiğini unutmayın:Rails.application.config.assets.precompile += %w( new_dir/js_file.js )
Jonesy


3

Benim anlayış varlık boru hattı tüm js birlikte (küçültülmüş) bir dosyada ezerek sayfa yükleme süresini azaltmak için amaçlanmıştır olduğunu. Bu yüzeyde iğrenç gibi görünse de, aslında C ve Ruby gibi popüler dillerde zaten var olan bir özelliktir. "İçerir" etiketleri gibi şeyler, bir dosyanın birden fazla eklenmesini önlemek ve programcıların kodlarını düzenlemelerine yardımcı olmak içindir. C'de bir program yazıp derlediğinizde, tüm bu kod çalışan programınızın her bölümünde bulunur, ancak yöntemler yalnızca bu kod kullanılırken belleğe yüklenir. Bir anlamda, derlenmiş bir program, kodun güzel bir şekilde modüler olduğunu garanti edecek hiçbir şey içermez. Programlarımızı bu şekilde yazarak kodu modüler hale getiriyoruz ve işletim sistemi sadece belirli bir yer için ihtiyacımız olan nesneleri ve yöntemleri belleğe yüklüyor. "Yönteme özgü dahil etme" diye bir şey bile var mı? Raylar uygulamanız dinlendirici ise, bu aslında istediğiniz şeydir.

Javascript'inizi sayfadaki HTML öğelerinin davranışını artıracak şekilde yazarsanız, bu işlevler tasarım gereği 'sayfaya özgü' olur. Bağlamına bakılmaksızın çalışacak şekilde karmaşık bir kod yazdıysanız, bu kodu yine de bir html öğesine bağlamayı düşünebilirsiniz ( Garber-Irish yönteminde açıklandığı gibi body etiketini kullanabilirsiniz ). Bir işlev koşullu olarak yürütülürse, performans muhtemelen bu ek komut dosyası etiketlerinden daha küçük olacaktır.

Palomayı kullanmayı düşünüyorumRails apps projesinde açıklandığı gibi gem . Ardından, paloma geri aramasına sayfaya özgü işlevleri ekleyerek javascript sayfanıza özgü yapabilirsiniz:

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

Rayları kullanıyorsun, bu yüzden mücevherleri sevdiğini biliyorum :)


3

Rails'i harika kılan önemli özellikleri kaybettiğiniz için JS veya CSS dosyalarınızı varlık kanalının dışına yüklememelisiniz. Ve başka bir mücevhere ihtiyacınız yok. Mümkün olduğunca az sayıda taş kullanmaya inanıyorum ve burada bir mücevher kullanmak gerekli değil.

Ne "Denetleyiciye Özel Javascript" ("Eylem Belirli Javascript altta bulunur) olarak bilinir Bu belirli bir KONTROLÖR için belirli bir JavaScript dosyası yüklemenizi sağlar .. Javascript bir görünümüne bağlamaya çalışıyorum tür .. MVC tasarım modelini takip etmez ve onu Kontrolörlerinizle veya Kontrolörlerinizdeki eylemlerle ilişkilendirmek istersiniz.

Ne yazık ki, herhangi bir nedenle, Rails devs varsayılan olarak her sayfanın varlık dizininizde bulunan her JS dosyasını yükleyeceğine karar verdi. Neden bunu varsayılan olarak "Denetleyici Özel Javascript" etkinleştirmek yerine yapmaya karar verdim asla bilemeyeceğim. Bu, varsayılan olarak aşağıdaki kod satırını içeren application.js dosyası aracılığıyla yapılır:

//= require_tree .

Bu yönerge olarak bilinir . Zincir dişlileri varlıklar / javascripts dizinindeki her JS dosyasını yüklemek için kullanır. Varsayılan olarak, zincir dişlileri application.js ve application.css dosyalarını otomatik olarak yükler ve requir_tree yönergesi her JS ve Coffee dosyasını ilgili dizinlerine yükler.

NOT: İskele yaptığınızda (iskele değilseniz, şimdi başlamak için iyi bir zamandır), Rails sizin için o iskele denetleyicisi için otomatik olarak bir kahve dosyası oluşturur . Bunu bir oluşturmak istiyorsanız standart JS yerine dosyayı kahve dosyası, daha sonra kaldırmak kahve mücevher sizin varsayılan olarak etkindir Gemfile ve JS yaratacak sizin iskele yerine dosyaları.

Tamam, bu yüzden "Denetleyiciye Özel Javascript" i etkinleştirmenin ilk adımı , request_tree kodunu application.js dosyanızdan kaldırmak, VEYA hala global JS dosyalarına ihtiyacınız varsa, varlıklar / javascripts dizininizdeki bir klasöre değiştirmek. IE:

//= require_tree ./global

Adım 2: config / initializers / asset.rb dosyanıza gidin ve aşağıdakileri ekleyin:

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

İstediğiniz Denetleyici adlarını ekleyin.

Adım 3: application.html.erb dosyanızdaki javascript_include_tag öğesini bununla değiştirin (params [: controller] bölümünü not edin:

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

Sunucunuzu yeniden başlatın ve viyola! İskele ile oluşturulan JS dosyası artık yalnızca o denetleyici çağrıldığında yüklenecektir.

IE / makaleler / yeni denetleyicinizdeki belirli bir EYLEM'e belirli bir JS dosyası yüklemeniz mi gerekiyor? Bunun yerine şunu yapın:

application.html.erb :

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

config / initializers / asset.rb :

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

Ardından varlıklar / javascripts klasörünüze denetleyicinizle aynı ada sahip yeni bir klasör ekleyin ve js dosyanızı içindeki eylemle aynı ada sahip bir yere yerleştirin. Daha sonra bu belirli eyleme yükleyecektir.


1

Tamam, belki de bu şimdiye kadarki en kötü iş gibi ama sadece .js dosyasını işleyen bir denetleyici yöntemi oluşturuyorum

kontrolör

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

Görünüm

%script{:src => @script, :type => "text/javascript"}

bir sebepten dolayı bunu yapmak istemiyorsak, bana bildirin.


1

JS eklemenin tercih edilen yolu altbilgidir, böylece şu şekilde yapabilirsiniz:

show.html.erb:

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

düzenleri / application.html.erb

<%= yield :footer_js %>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.