Raylar 4: Turbo bağlantılar ile $ (Document) .ready () nasıl kullanılır


422

JS dosyalarını "raylar yolu" düzenlemeye çalışırken Rails 4 uygulamamda bir sorunla karşılaştım. Daha önce farklı görüşlere dağılmışlardı. Onları ayrı dosyalar halinde düzenledim ve varlıklar kanalıyla derledim. Ancak, turbo-linking açıldığında jQuery'nin "hazır" etkinliğinin sonraki tıklamalarda tetiklenmediğini öğrendim. Bir sayfayı ilk kez yüklediğinizde çalışır. Ancak bir bağlantıyı tıkladığınızda, içindeki hiçbir şey ready( function($) {yürütülmez (sayfa gerçekte tekrar yüklenmediğinden). İyi açıklama: burada .

Benim sorum şu: Turbo bağlantılar açıkken jQuery olaylarının düzgün çalışmasını sağlamanın doğru yolu nedir? Betikleri Rails'e özgü bir dinleyiciye sarar mısınız? Ya da belki raylarda gereksiz kılan bir sihir vardır? Belgeler, özellikle application.js gibi manifest (ler) yoluyla birden fazla dosya yükleme konusunda, bunun nasıl çalışması gerektiği konusunda biraz belirsizdir.

Yanıtlar:


554

İşte yaptığım şey ... CoffeeScript:

ready = ->

  ...your coffeescript goes here...

$(document).ready(ready)
$(document).on('page:load', ready)

son satır, turbo bağlantılarının tetikleyeceği sayfa yükünü dinler.

Düzenle ... Javascript sürümü ekleniyor (istek başına):

var ready;
ready = function() {

  ...your javascript goes here...

};

$(document).ready(ready);
$(document).on('page:load', ready);

Düzenleme 2 ... Raylar 5 (Turbolinks 5) için page:loadolur turbolinks:loadve hatta ilk yüklemede ateş açılacak. Böylece aşağıdakileri yapabiliriz:

$(document).on('turbolinks:load', function() {

  ...your javascript goes here...

});

3
Bu kahve senaryosu mu? Henüz öğrenmedim. Örneğinize eşdeğer bir js veya jQuery var mı?
emersonthis

6
Sanırım anladım: İkisi ve tetiklenmesi var ready = function() { ... } $(document).ready(ready) $(document).on('page:load', ready)için endişe var mı ? .ready'page:load'
emersonthis

4
@Emerson açık bir adla çok kullanışlı bir web sitesi var: js2coffee.org
MrYoshiji

16
Hazır fonksiyon olmadığını teyit edebilir değil iki kez adlı. Zor bir yenileme ise, sadeceready olay tetiklenir. Bir turbolinks yük varsa, sadecepage:load olay tetiklenir. Bu ikisi için imkansız readyve page:loadaynı sayfada kovulmak üzere.
Christian

7
Bilginize Ayrıca birden olaylar için bu başvuruda bulunabilir page:loadve readyilk argumet için bir boşluk ayrılmış bir dize ekleyerek. $(document).on('page:load ready', ready);İkinci argüman, readybu yanıtın örneğini izleyerek isimlendirilecek bir işlevdir .
ahnbizcad

235

Bu sorunu çözmek için başka bir seçenek öğrendim. Eğer yüklerseniz mücevher bunun için Raylar Turbolinks olayları bağlayacak her zamanki şekilde jQuery yazabilirsiniz böylece olaylar. Sadece eklemek hemen sonra (varsayılan olarak: js manifest dosyasında ).jquery-turbolinksdocument.readyjquery.turbolinksjqueryapplication.js


2
Harika, teşekkürler! Tam olarak ihtiyacım olan şey. Raylar yolu. Ortak düşünce.
Jeremy Becker

6
Acording belgeler , eklemek gerekir //= require jquery.turbolinks(örneğin application.js) beyannamesine.
apocryphalauthor

1
@wildmonkey iki cevap birbirini dışlar. 0.o
ahnbizcad

1
Bu mücevheri eklerken ray sunucunuzu yeniden başlatmanız gerekiyor
Toby 1 Kenobi

21
Rails 4'ün artık varsayılan olarak jquery.turbolinks tarafından desteklenmeyen Turbolinks 5 olduğunu unutmayın! Bkz. Github.com/kossnocorp/jquery.turbolinks/issues/56
sebastian

201

Son zamanlarda onunla başa çıkmanın en temiz ve kolay anlaşılır yolunu buldum:

$(document).on 'ready page:load', ->
  # Actions to do

VEYA

$(document).on('ready page:load', function () {
  // Actions to do
});

DÜZENLE bağlı yetki verilmiş olaylarınız
varsa , bunları işlevin dışına eklediğinizden emin olun , aksi takdirde her birinde geri tepme olurdocumentreadypage:load olayda (aynı işlevlerin birden çok kez çalışmasına neden olur). Örneğin, böyle aramalarınız varsa:

$(document).on 'ready page:load', ->
  ...
  $(document).on 'click', '.button', ->
    ...
  ...

Onları dışarı çıkarın ready işlevden şöyle:

$(document).on 'ready page:load', ->
  ...
  ...

$(document).on 'click', '.button', ->
  ...

Adresine bağlı yetki verilen olayların olaya bağlı olması documentgerekmez ready.


9
Bu, ayrı bir ready()işlev oluşturmanın kabul edilen cevabından çok daha basittir . Delege edilen olayların readyfonksiyonun dışına bağlanması için bonus upvotes .
Christian

1
Bu yöntemin dezavantajı, $(document).on( "ready", handler ), deprecated as of jQuery 1.8. jquery / hazır
mfazekas

@Dezi @mfazekas jQuery'nin önceki sürümlerini ve jquery-turbolinks gem OLMADAN bu çözüm işe yarar mı? Yoksa readybölümü gem kullanarak geçersiz yapılan mı?
ahnbizcad

Bunu yapmanın en basit ve en kolay yolu. Birden fazla dosyaya dağıtılan js kodunu destekler ve hangi sırayla dahil edildiklerini rahatsız etmek zorunda değilim. Değişken atamadan çok daha temiz.
Evgenia Manolova

3
Muhtemelen "page: load" yerine "page: change" kullanmalısınız, çünkü sayfa sunucudan mı yoksa istemci tarafı önbelleğinden mi yüklenir ?
Nathan Long

91

Bunu Rails 4 belgesinde , DemoZluk'un çözümüne benzer, ancak biraz daha kısa bulundu:

$(document).on 'page:change', ->
  # Actions to do

VEYA

$(document).on('page:change', function () {
  // Actions to do
});

Arayan harici komut dosyalarınız $(document).ready()varsa veya mevcut tüm JavaScript'inizi yeniden yazmaktan rahatsız olamıyorsanız, bu değerli taş kullanmaya devam etmenizi sağlar$(document).ready() TurboLinks ile : https://github.com/kossnocorp/jquery.turbolinks


79

Yeni ray kılavuzlarına göre, doğru yol aşağıdakileri yapmaktır:

$(document).on('turbolinks:load', function() {
   console.log('(document).turbolinks:load')
});

veya kahve dilinde:

$(document).on "turbolinks:load", ->
alert "page has loaded!"

Etkinliği dinlemeyin, $(document).readyyalnızca bir etkinlik başlatılacaktır . Sürpriz yok, jquery.turbolinks gem kullanmaya gerek yok .

Bu, sadece raylar 5 ile değil, 4.2 ve üstü raylarla çalışır.


güzel bu benim için çalıştı. Burada denenmiş çözüm: stackoverflow.com/questions/17881384/… ancak bir nedenden dolayı çalışmadı. Şimdi turbolinklere yüklüyorum: bunun yerine yükle
krinker

1
Herkes "turbolinks:load"Rails 4.2'de çalıştığını doğrulayabilir mi? turbolinks:Olay öneki tanıtıldı Yeni Turbolinks ve Rails Turbolinks kullanan 4.2 IIRC kullanılmaz Klasik . Deneyebilirsiniz "page:change"eğer "turbolinks:load"senin çalışmıyor 5 app öncesi-Raylar. Bkz. Guides.rubyonrails.org/v4.2.7/…
Eliot Sykes

1
@EliotSykes Kılavuz güncellenmedi. 4,2 şimdi kullandığı raylar github.com/turbolinks/turbolinks turbolinks-klasik yerine. Ve her durumda, bu Gemfile'da belirttiğinize bağlıdır. Umarım yakında aynı şeyi
onaylarsınız

3
Teşekkürler vedant1811. Yazarken, yeni bir Rails 4.2.7 uygulamasının Turbolinks 5 (turbolinks-classic değil) kullandığını onaylıyorum. Bunu okuyan geliştiriciler - kullanılan turbolinks sürümü için Gemfile.lock'unuzu kontrol edin. page:change5.0'dan küçükse turbolinkleri kullanın veya yükseltin. Ayrıca, turbolinks'in olayları eski olay adlarına çevirdiği bazı kişilerle ilgili olabilir: github.com/turbolinks/turbolinks/blob/v5.0.0/src/turbolinks/…
Eliot Sykes

1
alert "page has loaded!"Geri arama işlevi tarafından çalıştırılmak üzere girintilenme ihtiyacı var mı ?
mbigras

10

NOT: Temiz, yerleşik bir çözüm için @ SDP'nin cevabına bakın

Aşağıdaki gibi sabitledim:

Diğer uygulama bağımlı js dosyaları dahil etmeden önce dahil etme sırasını aşağıdaki gibi değiştirerek application.js'yi eklediğinizden emin olun:

// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .

Bağlanmayı işleyen genel bir işlev tanımlayın application.js

// application.js
window.onLoad = function(callback) {
  // binds ready event and turbolink page:load event
  $(document).ready(callback);
  $(document).on('page:load',callback);
};

Şimdi aşağıdaki gibi şeyler bağlayabilirsiniz:

// in coffee script:
onLoad ->
  $('a.clickable').click => 
    alert('link clicked!');

// equivalent in javascript:
onLoad(function() {
  $('a.clickable').click(function() {
    alert('link clicked');
});

2
Bunu en temiz görünüyor çünkü bunu sadece tek bir yere eklemek zorundasınız, her kahve dosyasını değil. İyi iş!
pyrospade

@sled Bu SDP'nin gem ve bu kodu kullanma yöntemini kullanmak mı diyor? Yoksa bu cevabı kullanmayan bir cevap mı?
ahnbizcad

bu cevabı unut ve SDP'nin çözümünü kullan.
kızak

@sled SDP'nin çözümünü, çağrıyı yalnızca tek bir yere koyma fikriyle birleştirmek mümkün mü?
ahnbizcad

1
@gwho: As SDP'nin cevabı gösterileri, turbolinks kadar kanca readyEğer başlatılıyor "standart" şekilde kullanabilirsiniz bu araçlar, olay: $(document).ready(function() { /* do your init here */});. Tüm sayfa yüklendiğinde (turbolinkler olmadan) init kodunuz çağrılmalı ve turbolinkler aracılığıyla bir sayfa yüklediğinizde init kodunuz tekrar çalıştırılmalıdır. SADECE bir turbolink kullanıldığında bazı kodları yürütmek istiyorsanız:$(document).on('page:load', function() { /* init only for turbolinks */});
kızak

8

Yukarıdakilerin hiçbiri benim için çalışmıyor, bunu jQuery's $ (document) .ready kullanarak çözdüm, ancak bunun yerine addEventListener kullanın.

document.addEventListener("turbolinks:load", function() {
  // do something
});

7
$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'

Bu benim için her tarayıcıda, Turbolinks> = 5 için çalışan ve hem ilk sayfa yüklemesinde hem de herhangi bir bağlantıyı (turbolinklerle) tıkladığınızda çalışan tek çözümdür. Yani Chrome tetikleyiciler ederken nedeniyle böyledir turbolinks:loadilk sayfa yüklemesinde, Safari bunu düzeltmek için değil ve hacky yolu yok (tetikleme turbolinks:loadüzerine application.js) besbelli (Bu iki kez ateşler) Krom kırar. Bu doğru cevap. Kesinlikle 2 olayları ile gidin readyve turbolinks:load.
lucasarruda



2

"Hazır" işlevini kaydetmek ve olaylara bağlamak için bir değişken kullanmak yerine, readyher page:loadtetiklendiğinde olayı tetiklemek isteyebilirsiniz .

$(document).on('page:load', function() {
  $(document).trigger('ready');
});

2

İşlerin iki kez yürütülmemesini sağlamak için yaptığım şey:

$(document).on("page:change", function() {
     // ... init things, just do not bind events ...
     $(document).off("page:change");
});

jquery-turbolinksMücevher kullanarak veya birleştirerek $(document).readyve / $(document).on("page:load")veya $(document).on("page:change")kendi başına kullanmak beklenmedik şekilde davranıyor - özellikle de geliştirme aşamasındaysanız.


Ne demek istediğinizi açıklamak beklenmedik bir şekilde davranıyor mu?
sunnyrjuneja

Eğer $(document).offo anonim "page: change" fonksiyonunda bit olmadan sadece basit bir uyarı varsa o sayfaya geldiğimde açıkça uyarır. Ancak en azından WEBrick çalıştıran geliştirme aşamasında, başka bir sayfaya giden bir bağlantıyı tıkladığımda da uyarılacak. Daha da kötüsü, daha sonra orijinal sayfaya giden bir bağlantıyı tıkladığımda iki kez uyarır.
Gri Kemmey

2

Benim için harika çalışan ve aşağıdakilerin kullanımını detaylandıran aşağıdaki makaleyi buldum :

var load_this_javascript = function() { 
  // do some things 
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)


2
$(document).ready(ready)  

$(document).on('turbolinks:load', ready)

2
Bu kod snippet'i soruyu çözebilir, ancak bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın.
andreas

4
Aslında bu cevap yanlış. turbolinks:loadİlk sayfanın yüklenmesini yanı sıra aşağıdaki bağlantılardan sonra olayı harekete. Eğer hem standart için bir etkinlik eklerseniz readyolay ve turbolinks:loadolay önce bir sayfayı ziyaret ettiğinizde, iki kez tetiklenir.
alexanderbird

Bu cevap yanlış. @Alexanderbird'ün dediği gibi, readysonraki sayfa yüklemelerinde iki kez tetiklemeye neden olur . Lütfen değiştirin veya kaldırın.
chester

@alexanderbird Yorumunuz benim için sorunlardan birini çözdü
Anwar

1

Sonunda bu kadar çok çözümün geldiğini test etti. Bu birçok kod kesinlikle iki kez çağrılmaz.

      var has_loaded=false;
      var ready = function() {
        if(!has_loaded){
          has_loaded=true;
           
          // YOURJS here
        }
      }

      $(document).ready(ready);
      $(document).bind('page:change', ready);


1

Raylarım 4 projeleri için genellikle aşağıdakileri yaparım:

İçinde application.js

function onInit(callback){
    $(document).ready(callback);
    $(document).on('page:load', callback);
}

Sonra js dosyalarının geri kalanı, yerine kullanarak $(function (){})ÇağrıyıonInit(function(){})


0

İlk olarak, jquery-turbolinksgem yükleyin . Ve sonra, senin gövdesinin ucundan senin dahil JavaScript dosyaları taşımak için unutma application.html.erbonun için <head>.

Burada açıklandığı gibi , uygulama javascript bağlantısını hız optimizasyonu nedeniyle altbilgiye koyduysanız, etiketin içeriğinden önce yüklenmesi için etikete taşımanız gerekir. Bu çözüm benim için çalıştı.


0

Bir işlevi kullanırken işlevlerimi iki katına çıkardım readyve turbolinks:loadkullandım,

var ready = function() {
  // you code goes here
}

if (Turbolinks.supported == false) {
  $(document).on('ready', ready);
};
if (Turbolinks.supported == true) {
  $(document).on('turbolinks:load', ready);
};

Bu şekilde, turbolinkler destekleniyorsa işlevleriniz iki katına çıkmaz!

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.