RailsのTurbolinksとVue.jsを共存させる方法

  • 0
    いいね
  • 0
    コメント

    はじめに

    ジドウシャ部ではフロントエンドにRails + Turbolinks + Vue.jsを採用しています。

    Turbolinksといえば敬遠されがちなRails標準ライブラリですが、ジドウシャ部ではTurbolinksを活用し、スマホブラウザでもアプリに近いUIを実現しています。

    本記事では Turbolinks と Vue.js を併用する上で解決すべき課題と、解決策の一例をご紹介します。

    解決すべき課題

    TurbolinksとVueを共存させる上で解決すべき課題は下記の2点です。

    • Vueのマウントタイミング
      • マウントするタイミングによってはエレメントが存在しないケースが発生します
    • ヒストリーバック時の処理
      • Turbolinksのヒストリーバック機能ではVueが正しく復元されません

    解決策

    Vueのマウントタイミング制御

    データ属性にマウントするVueの情報を埋め込み、Turbolinksのロードイベントでデータ属性を探してマウントする方法で解決しました。

    データ属性でマウントするVueを指定

    / example.slim
    .example data-vue='ExampleVue'
    

    Turbolinksのロードイベントで data-vue 属性を走査しマウント

    # example.coffee
    document.addEventListener 'turbolinks:load', ->
      for el in document.querySelectorAll('[data-vue]')
        v = eval(el.dataset.vue)
        v.el = el
        new Vue (v)
    

    ヒストリーバック時の処理

    Turbolinksのヒストリーバックは、キャッシュからロードを行うことで高速なヒストリーバックを実現しています。しかしページ遷移時のDOMを cloneNode(true) で復元するため、イベントハンドラが削除され、v-*属性も Vueをマウントした段階で消えるため、Vueが正しく動作しなくなります。

    様々な方法を試みましたが、残念ながらTurbolinksのキャッシュ機能を無効にする以外の対応はできないという結論です。

    meta name="turbolinks-cache-control" content="no-cache"
    

    head内に上記のmetaタグを設置することでTurbolinksのキャッシュを無効化できます。

    最後に

    Backbone.js、Mithril.js、riot.jsなどで一通りシステムを組み上げてきましたが、Vue.jsはRails(+Turbolinks)とかなり相性が良いライブラリだと思います。ぜひこの組み合わせをお試しください。

    参考