2017-04-05 4 views
1

Turbolinks 5がすごく優れている理由は分かっていますが、読んでいるとすればおそらく同様ですが、ブロック上の他のスクリプトとの間にどれほど重大な悪影響を及ぼしているのか非常に不満です。Turbolinks unfriendly?

現在まで、既存のjQueryスクリプトを機能させる方法でラップする方法を示す簡単な説明はありません。 たとえば、これを取る:https://github.com/Bttstrp/bootstrap-switch。それはよく書かれており、理解しやすいです。 jsとcssをアセットパイプラインにロードし、一部のページでインスタンス化します。

# view.html.erb 
<input type="checkbox" class="switch"> switch button 
<script type="text/javascript"> 
    $(".switch").bootstrapSwitch(); 
</script> 

view.htmlに行き、別のページをクリックして戻ると2つのボタンが表示されます。

次に、TurbolinksにbootstrapSwitchのインスタンスをロードする方法を探しています。さて、もしあなたがそうしても、機能はなくなります。クリックすると動作しません。

$(document).on("turbolinks:load", function()...は、すべてのTurbolink訪問でそれをロードしますし、今のところ、私は重複を作成しそれを動作させるとことができませんでした唯一の方法はちょっと愚か感じる

<%= content_for :head do %> 
    <meta name="turbolinks-cache-control" content="no-cache"> 
<% end %> 

でview.html上のキャッシュを無効にすることでした。

私はそれが偶像性を使用することと何か関係があると思います - https://github.com/turbolinks/turbolinks#making-transformations-idempotentしかし、実際にはどうしますか?

この単純なプラグインを例に挙げて、他のスクリプトで再現できるシンプルで洗練されたソリューションを共有してください。

+1

私はTurboLinksについてよく知りませんが、簡単な回避策があると思います。以前に '.bootstrapSwitch();'が呼び出されたかどうかをテストするラッパー関数を作成してみてくださいそれは最初の実行で... – Myst

答えて

0

Turbolinksでアプリを開発するには、スムーズに動作させるために特別な方法が必要です。ページがロードされてキャッシュされる方法の違いによって、実行中のスクリプトのいくつかのパターンは、Turbolinksと同等の方法では動作しません。これは最初は不愉快に思えるかもしれませんが、「落ち着き」はイライラするかもしれませんが、少し理解すれば、より組織的で堅牢なコードを奨励しています:)

あなたが理解したように、スイッチは、プラグインが同じ要素に対して複数回呼び出されていることです。これは、Turbolinksがページをちょうどからキャッシュするためです。キャッシュされたバージョンには、動的に追加されたHTML [1]などが含まれています。プラグインを介して追加されたものバック/フォワードをナビゲートすると、キャッシュされたバージョンが復元され、動作は重複します。/

これを修正するにはどうすればよいですか。 HTMLまたはイベントリスナーを追加するコードを操作するときは、ページがキャッシュされる前に振る舞いを解除するのが一般的です。そのためのTurbolinksイベントはturbolinks:before-cacheです。だからあなたのセットアップ/ティアダウンは次のようになります。

// app/assets/javascripts/switches.js 
$(document) 
    .on('turbolinks:load', function() { 
    $('.switch').bootstrapSwitch() 
    }) 
    .on('turbolinks:before-cache', function() { 
    $('.switch').bootstrapSwitch('destroy') 
    }) 

すべてのセットアップとティアダウンは、イベントハンドラで行われているので、このテストには少し難しいです。さらに、もっと多くのケースがあるかもしれないので、反復を避けるために、機能を設定し、解体するための独自の「ミニフレームワーク」を導入したいと思うかもしれません。以下では、基本的なフレームワークの作成について説明します。

これは私たちが目指すものです。window.App.addFunctionを名前と関数に呼び出すと、呼び出す関数が登録されます。その関数は要素を取得し、プラグインを呼び出します。アプリの初期化時に私たちは、それぞれの関数を呼び出します

// app/assets/javascripts/application.js 
// … 
window.App = { 
    functions: {}, 

    addFunction: function (name, fn) { 
    this.functions[name] = fn 
    } 
} 

、および:

// app/assets/javascripts/switches.js 
window.App.addFunction('switches', function() { 
    var $switches = $('.switch').bootstrapSwitch() 
    return { 
    destroy: function() { 
     $switches.bootstrapSwitch('destroy') 
    } 
    } 
}) 

次実装addFunctionfunctionsプロパティに追加された機能を格納する:それはティアダウンのためにdestroy機能を持つオブジェクトを返します。それが存在する場合resultsアレイ内の各関数呼び出しの結果を格納します。

// app/assets/javascripts/application.js 
// … 
var results = [] 

window.App = { 
    // … 
    init: function() { 
    for (var name in this.functions) { 
     var result = this.functions[name]() 
     if (result) results.push(result) 
    } 
    } 
} 

// app/assets/javascripts/application.js 
// … 
window.App = { 
    // … 
    destroy: function() { 
    for (var i = 0; i < results.length; i++) { 
     var result = results[i] 
     if (typeof result.destroy === 'function') result.destroy() 
    } 
    results = [] 
    } 
} 

は最後に初期化してアプリをティアダウン:

$(document) 
    .on('turbolinks:load', function() { 
    window.App.init.call(window.App) 
    }) 
    .on('turbolinks:before-cache', window.App.destroy) 

だから、すべて一緒にこれを置くために:

;(function() { 
    var results = [] 

    window.App = { 
    functions: {}, 

    addFunction: function (name, fn) { 
     this.functions[name] = fn 
    }, 

    init: function() { 
     for (var name in this.functions) { 
     var result = this.functions[name]() 
     if (result) results.push(result) 
     } 
    }, 

    destroy: function() { 
     for (var i = 0; i < results.length; i++) { 
     var result = results[i] 
     if (typeof result.destroy === 'function') result.destroy() 
     } 
     results = [] 
    } 
    } 

    $(document) 
    .on('turbolinks:load', function() { 
     window.App.init.call(window.App) 
    }) 
    .on('turbolinks:before-cache', window.App.destroy) 
})() 
アプリをダウンARINGしても、結果に(存在する場合) destroyを呼び出して破壊する必要

関数は、関数を呼び出すイベントハンドラから独立しています。このデカップリングには2つの利点があります。最初にもっとテスト可能です:関数はwindow.App.functionsで利用できます。また、いつ機能を呼び出すかを選択することもできます。たとえば、ターボリンクを使用しないと決めた場合、変更する必要があるのはwindow.App.initと呼ばれる部分だけです。


は、[1]私は、これは(それが最初にロードされたとき、それがあったようにページに戻って、ユーザーを返す「戻る」を押し)、デフォルトのブラウザの動作よりも優れていると思います。 Turbolinksの "Back"は、ユーザーがページを離れたときにそのページに戻ってきます。おそらくユーザーが期待しているものです。

関連する問題