Rails 4 : 터보 링크와 함께 $ (document) .ready ()를 사용하는 방법


422

JS 파일을 "레일 방식"으로 구성하려고 할 때 Rails 4 앱에서 문제가 발생했습니다. 그들은 이전에 다른 견해에 흩어져있었습니다. 파일을 별도의 파일로 구성하고 자산 파이프 라인으로 컴파일했습니다. 그러나 터보 링크가 켜져있을 때 jQuery의 "준비"이벤트가 후속 클릭에서 발생하지 않는다는 것을 알게되었습니다. 페이지를 처음로드하면 작동합니다. 그러나 링크를 클릭 ready( function($) {하면 페이지가 실제로 다시로드되지 않기 때문에 내부의 어떤 것도 실행되지 않습니다. 좋은 설명 : here .

그래서 내 질문은 : 터보 링크가 켜져있는 동안 jQuery 이벤트가 올바르게 작동하도록하는 올바른 방법은 무엇입니까? Rails 전용 리스너에서 스크립트를 래핑합니까? 아니면 레일에 불필요하게 만드는 마법이 있습니까? 문서는 특히 application.js와 같은 매니페스트를 통해 여러 파일을로드하는 것과 관련하여 이것이 어떻게 작동하는지 조금 모호합니다.

답변:


554

여기 내가하는 일이 있습니다 : CoffeeScript :

ready = ->

  ...your coffeescript goes here...

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

마지막 줄은 터보 링크가 트리거 할 페이지로드를 청취합니다.

편집 ... 자바 스크립트 버전 추가 (요청 당) :

var ready;
ready = function() {

  ...your javascript goes here...

};

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

편집 2 ... 레일 5 (Turbolinks 5)의 경우는 page:load되고 turbolinks:load, 심지어 초기로드에 발사 될 것이다. 따라서 다음을 수행 할 수 있습니다.

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

  ...your javascript goes here...

});

3
커피 스크립트인가요? 아직 배우지 못했습니다. 귀하의 예제와 동등한 js 또는 jQuery가 있습니까?
emersonthis

6
내가 그것을 가지고 생각 : var ready = function() { ... } $(document).ready(ready) $(document).on('page:load', ready)에 대한 우려가 있습니까 모두 .ready'page:load'트리거하기는?
emersonthis

4
@Emerson 매우 명쾌한 이름을 가진 매우 유용한 웹 사이트가 있습니다 : js2coffee.org
MrYoshiji

16
ready 함수가 두 번 호출 되지 않는 것을 확인할 수 있습니다 . 그것은 새로 고침의 경우 에만ready 이벤트가 발생합니다. 그것은 turbolinks 부하의 경우 에만page:load 이벤트가 발생합니다. 그것은 모두 불가능 readypage:load동일한 페이지에 발사 할 수 있습니다.
Christian

7
참고 또한 여러 이벤트에 대해이 작업을 적용 할 수 있습니다 page:loadready첫 argumet에 대한 공백으로 구분 된 문자열을 포함하여. $(document).on('page:load ready', ready);두 번째 인수는 단순히 함수이며, ready이 대답의 예에 따라 이름 이 지정 됩니다.
ahnbizcad

235

나는이 문제를 해결하기위한 또 다른 옵션을 배웠다. gem 을로드 하면jquery-turbolinks Rails Turbolinks 이벤트를 이벤트에 바인딩 document.ready하여 일반적인 방식으로 jQuery를 작성할 수 있습니다. js manifest 파일 jquery.turbolinks바로 뒤에 추가 jquery하면됩니다 (기본 :) application.js.


2
정말 고마워요! 정확히 내가 필요한 것. 가로장 길. 협약.
Jeremy Becker

6
주문에 따라 문서 , 당신은 추가해야합니다 //= require jquery.turbolinks(예 : application.js) 매니페스트에.
apocryphalauthor

1
@ wildmonkey 두 답변은 상호 배타적입니다. 0.o
ahnbizcad

1
이 gem을 추가 할 때 rails 서버를 다시 시작해야합니다
Toby 1 Kenobi

21
Rails 4는 이제 기본적으로 Turbolinks 5로 설정되어 있으며 jquery.turbolinks는이를 지원하지 않습니다! github.com/kossnocorp/jquery.turbolinks/issues/56
sebastian

201

최근에 가장 깨끗하고 이해하기 쉬운 방법을 찾았습니다.

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

또는

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

편집에 바인딩 된 이벤트를 위임 한
경우 함수 외부에 첨부해야 합니다. 그렇지 않으면 동일한 함수가 여러 번 실행되므로 모든 이벤트에서 리바운드됩니다 . 예를 들어 다음과 같은 호출이있는 경우 :documentreadypage:load

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

다음 ready과 같이 기능에서 꺼내십시오 .

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

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

에 바인딩 된 위임 된 이벤트는 이벤트에 바인딩 document될 필요가 없습니다 ready.


9
이것은 별도의 ready()함수 를 만드는 데 허용되는 답변보다 훨씬 간단 합니다. ready함수 외부에서 위임 된 이벤트를 바인딩하는 방법에 대한 보너스 공감
Christian

1
이 방법의 단점은 $(document).on( "ready", handler ), deprecated as of jQuery 1.8. jquery / ready
mfazekas

@Dezi @mfazekas 이전 버전의 jQuery를 사용하고 jquery-turbolinks gem이없는 경우이 솔루션이 작동합니까? 아니면 ready보석을 사용하여 부분이 유효하지 않게됩니까?
ahnbizcad

가장 간단하고 쉬운 방법입니다. 여러 파일로 배포 된 js 코드를 지원하며 포함 된 순서를 귀찮게 할 필요가 없습니다. 변수 할당보다 훨씬 깨끗합니다.
Evgenia Manolova


91

이 발견 레일 4 문서 DemoZluk의 솔루션과 유사하지만 약간 짧은을 :

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

또는

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

호출하는 외부 스크립트가 $(document).ready()있거나 기존 JavaScript를 모두 다시 작성할 필요가없는 경우이 gem을 사용하면 $(document).ready()TurboLinks 를 계속 사용할 수 있습니다 . https://github.com/kossnocorp/jquery.turbolinks


79

새로운 레일 가이드 에 따라 올바른 방법은 다음을 수행하는 것입니다.

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

또는 커피 스크립트에서 :

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

이벤트를 듣지 마십시오 $(document).ready. 하나의 이벤트 만 시작됩니다. 당연히 jquery.turbolinks gem 을 사용할 필요가 없습니다 .

이것은 레일 5 이상이 아니라 레일 4.2 이상에서 작동합니다.


좋은 이것은 나를 위해 일했다. 해결책을 시도했습니다 : stackoverflow.com/questions/17881384/… 그러나 어떤 이유로 작동하지 않았습니다. 이제
터보 링크를

1
누구나 "turbolinks:load"Rails 4.2에서 이벤트가 작동 하는지 확인할 수 있습니까 ? turbolinks:이벤트 접두어는에 도입 된 새로운 Turbolinks 및 레일에 Turbolinks 사용 4.2 IIRC 사용하지 않는 클래식 . pre-Rails 5 앱에서 작동하지 않는 "page:change"경우 "turbolinks:load"사용해 보십시오 . guides.rubyonrails.org/v4.2.7/…
Eliot Sykes

1
@EliotSykes 가이드가 업데이트되지 않았습니다. Rails 4.2는 이제 turbolinks-classic 대신 github.com/turbolinks/turbolinks 를 사용합니다 . 그리고 어쨌든 이것은 Gemfile에 지정한 내용에 따라 다릅니다. :)
vedant

3
감사합니다 @ vedant1811. 글을 쓰는 시점에서 새로운 Rails 4.2.7 앱이 Turbolinks 5 (터보 링크 클래식이 아님)를 사용하고 있음을 확인하고 있습니다. 이것을 읽는 개발자-사용 된 터보 링크 버전은 Gemfile.lock을 확인하십시오. 5.0보다 작은 경우 page:change터보 링크 를 사용 하거나 업그레이드하십시오. 또한 터보 링크
Eliot Sykes

1
alert "page has loaded!"실제로 콜백 함수에 의해 실행되도록 들여 쓰기가 필요 합니까 ?
mbigras

10

참고 : 깨끗하고 내장 된 솔루션은 @SDP의 답변을 참조하십시오

다음과 같이 수정했습니다.

다음과 같이 포함 순서를 변경하여 다른 앱 종속 js 파일이 포함되기 전에 application.js를 포함시켜야합니다.

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

바인딩을 처리하는 전역 함수를 정의하십시오. application.js

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

이제 다음과 같은 것을 묶을 수 있습니다.

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

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

2
이것은 모든 커피 스크립트 파일이 아니라 한 곳에만 추가해야하기 때문에 가장 깨끗한 것 같습니다. 잘 했어!
pyrospade

@sled 이것이 보석과이 코드를 사용하는 SDP의 방법을 사용한다는 말입니까? 아니면 보석을 사용하지 않는 대답입니까?
ahnbizcad

이 답변을 잊어 버리고 SDP의 솔루션을 사용하십시오.
썰매

@sled SDP의 솔루션을 한 곳에만 전화한다는 개념을 결합 할 수 있습니까?
ahnbizcad

1
@gwho : SDP의 답변에서 볼 수 있듯이 터보 링크는 ready이벤트에 연결되므로 "표준"초기화 방법을 사용할 수 있습니다 $(document).ready(function() { /* do your init here */});. 전체 페이지가로드되면 (-> 터보 링크 없음) 초기화 코드를 호출해야하고 터보 링크를 통해 페이지를로드하면 초기화 코드를 다시 실행해야합니다. 터보 링크가 사용될 때만 일부 코드를 실행하려면 :$(document).on('page:load', function() { /* init only for turbolinks */});
sled

8

위의 어느 것도 나를 위해 작동하지 않습니다 .jQuery의 $ (document) .ready를 사용하지 않고이 문제를 해결했지만 대신 addEventListener를 사용하십시오.

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

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

그것은 모든 브라우저에서 나를 위해 작동하는 유일한 솔루션입니다. Turbolinks> = 5의 경우 첫 페이지로드 및 링크 (터보 링크 포함)를 클릭 할 때 모두 트리거됩니다. 즉 크롬 트리거 중에 있기 때문에 경우가 turbolinks:load맨 처음 페이지로드는, 사파리는 그것을 해결하기 위해하지와 해키 방법 않습니다 (트리거 turbolinks:loadapplication.js) 분명히 (이 두 번 발사) 크롬 나누기. 이것이 정답입니다. 확실히 2 이벤트 ready와 함께 가십시오 turbolinks:load.
lucasarruda



2

변수를 사용하여 "준비"기능을 저장하고 이벤트에 바인딩하는 대신 트리거 ready될 때마다 이벤트 를 트리거 할 수 있습니다 page:load.

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

2

작업이 두 번 실행되지 않도록하기 위해 수행 한 작업은 다음과 같습니다.

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

나는 jquery-turbolinks 보석을 사용하거나 결합 $(document).ready하고 $(document).on("page:load")사용 $(document).on("page:change")하는 것 자체가 예기치 않게 행동 특히 개발중인 경우.


뜻하는 바가 뜻밖의 행동인지 설명해 주시겠습니까?
sunnyrjuneja

$(document).off위의 익명의 "page : change"함수에 비트가 없는 간단한 경고가있는 경우 해당 페이지에 도착하면 분명히 경고합니다. 그러나 적어도 WEBrick을 실행하는 개발에서는 다른 페이지에 대한 링크를 클릭하면 경고합니다. 더 나쁜 것은 원래 페이지로 돌아가는 링크를 클릭하면 두 번 경고합니다.
그레이 케미

2

나는 나에게 잘 맞는 다음 기사 를 발견하고 다음 사용법을 자세히 설명합니다.

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
이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 귀하의 코드 제안 이유를 모를 수도 있습니다.
andreas

4
실제로이 답변은 틀 렸습니다. turbolinks:load초기 페이지로드뿐만 아니라 다음 링크 후 이벤트가 발생합니다. 표준 ready이벤트와 이벤트 모두에 이벤트를 첨부 turbolinks:load하면 처음 페이지를 방문 할 때 두 번 발생합니다.
alexanderbird

이 답변은 잘못되었습니다. @alexanderbird가 말했듯이 ready후속 페이지로드에서 두 번 발생 합니다. 변경하거나 제거하십시오.
체스터

@alexanderbird 귀하의 의견은 저를위한 문제 중 하나를 해결했습니다
Anwar

1

많은 솔루션이 마침내 이것에 도달했습니다. 이 많은 코드는 확실히 두 번 호출되지 않습니다.

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

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


1

나는 보통 레일 4 프로젝트에 대해 다음을 수행합니다.

application.js

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

그런 다음 나머지 .js 파일에서 $(function (){})전화 를 사용하는 대신onInit(function(){})


0

먼저 jquery-turbolinksgem을 설치하십시오 . 그리고, 당신의 몸의 끝에서 포함 된 자바 스크립트 파일을 이동하는 것을 잊지 마세요 application.html.erb그것으로 <head>.

으로 여기에 설명 이 속도 최적화 이유로 바닥 글에서 응용 프로그램의 자바 스크립트 링크를 넣어 경우, 당신은 너무 태그로 이동해야합니다 그것이로드 태그의 콘텐츠 전에. 이 솔루션은 저에게 효과적이었습니다.


0

내가하는 기능을 사용할 때 제 기능을 두 배로 발견 ready하고 turbolinks:load, 내가 사용하므로

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

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

그렇게하면 터보 링크가 지원되는 경우 함수가 두 배가되지 않습니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.