Barba.jsによる画面遷移を使う

githubに下記のサンプルコードを上げました。
https://github.com/NomuraS/qiita-barba

#barba.jsとは
[barba.js](http://barbajs.org/)とは、pushStateとAjaxをまとめて使いやすくしたpjaxをさらに使いやすくしたものです。具体的にこれがどのようなものかは[こちら](https://oku-log.com/pjax-barba/)が詳しく解説してくれています。barba.js(pjax)を導入する意味は少なくとも以下のようなものがあると考えています。

- ajaxによる円滑な画面遷移とpushStateによるブラウザ履歴への登録。
- 画面遷移時にパワーポイントのようなアニメーションを簡単に付けられる。
- htmlをパーツに分けてモジュール化する。

#基本的な使い方

画面遷移のアニメーションにこだわらず、barba.jsを導入するだけだったら本当に簡単です。以下の2つのhtmlファイルを用意します。

```html:page1.html
<!DOCTYPE html>
<html>

<head>
    <title>Barba.jsテスト</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/barba.js/1.0.0/barba.min.js"></script>
    <script src="http://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>

<body>
    header - unchange
    <ul>
        <li>
            <a href="./page2.html">link to page2</a>
        </li>
        <li>
            <a href="./page1.html">link to page1</a>
        </li>
    </ul>
    <main id="barba-wrapper">
        <div class="barba-container">
            ここを変更する。
        </div>
    </main>
    footer - unchange
</body>
<script>
    Barba.Pjax.init();
</script>

</html>
```

```html:page2.html
<!DOCTYPE html>
<html>
<body>
    <main id="barba-wrapper">
        <div class="barba-container">
            変更しました。
        </div>
    </main>
</body>

</html>
```

ローカルサーバーを例えば次のように立ち上げて、

```sh:console
python3 -m http.server 8080
```

その後、`http://localhost:8080/page1.html`にアクセスし、「link to page2」というリンクをクリックした後、「ここを変更する。」の部分だけが変更され、headerとfooterとリンクの部分が残っているか確認してみます。

#画面遷移時のアニメーション
Barba.jsを使うことで画面遷移時にパワーポイントのようなアニメーションをつけることができます。個人的にこれはあまり重要視しておらず公式で紹介されているフェードアウトのアニメーションだけで十分ですので、それだけ紹介します。

```js:フェードアウト
var FadeTransition = Barba.BaseTransition.extend({
  start: function() {

    Promise
      .all([this.newContainerLoading, this.fadeOut()])
      .then(this.fadeIn.bind(this));
  },

  fadeOut: function() {
    return $(this.oldContainer).animate({ opacity: 0 }).promise();
  },

  fadeIn: function() {

    var _this = this;
    var $el = $(this.newContainer);

    $(this.oldContainer).hide();

    $el.css({
      visibility : 'visible',
      opacity : 0
    });

    $el.animate({ opacity: 1 }, 400, function() {
      _this.done();
    });
  }
});

Barba.Pjax.getTransition = function() {
  return FadeTransition;
};
```

このコードをpage1.htmlのBarba.Pjax.init();のすぐ下に貼り付ければ遷移時にフェードアウトで遷移するようになります。アニメーションはanimate()やcssを変更すれば好きにカスタマイズできるようです。


#事前読み込みPrefetch
リンクをクリックする前のマウスオーバーした際に、自動でリンク先を読み込み、よりラグの少ない遷移を可能にします。これも簡単で、Barba.Pjax.init();のすぐ下にBarba.Prefetch.init();と書くだけです。

Prefetchと上のアニメーションの記述もまとめると次のようになります。


```js
Barba.Pjax.init();
Barba.Prefetch.init();
var FadeTransition = Barba.BaseTransition.extend({
　　　　　省略
});

Barba.Pjax.getTransition = function() {
  return FadeTransition;
};
```

#ブラウザのリロードの問題
barbaとpjaxに共通して個人的に問題だと思うのが、画面遷移先(上の例のpage2.html)でブラウザをf5などで更新した場合、更新先のhtmlだけが読み込まれるため、上の例のfooterやheader、そしてリンクは消えます。どうにかならないものかと調べましたが、pjaxのほうの[質疑応答](https://github.com/defunkt/jquery-pjax/issues/481)によるとどうにもならないということでした。

これを解決するためには、body全体をbarba-wrapperで括ってしまい、遷移先でも全く同じhtmlのパーツ(headerなど)を書いておけば当然、遷移先で更新してもレイアウトは崩れません。[公式のDEMO](http://barbajs.org/demos.html)もそのようにしています。

しかし、この解決法は最初に確認したbarba.js導入のメリットであるhtmlのモジュール化を否定してしまうどころか、遷移先にまったく同じ記述をかからなくてはなりません。これだったら他のテンプレートエンジンを導入したほうが幾分マシです。

barba(pjax)を捨てるか、リロードを捨てるか迷った挙句、結局、リロード先をトップページにするという妥協策でbarba.jsを導入しました。つまり、page2.htmlでリロードした場合、page1.htmlに飛ぶようにjsを一行加えました。

```html:page2.htmlにhead追加
  <head>
    <script>
        window.location.href = "./page1.html";
    </script>
  </head>
```
これでpage2でリロードした場合、page1に飛びます。



#javascriptのイベント
画面遷移では$(document).readyが発火しないだけでなく、クリックイベントなどもhtmlに付しません。そこで、次のようなbarba特有の表現でイベントをラップしてあげます。

```js
Barba.Dispatcher.on('newPageReady', function () {
    $(document).ready(function () {
        console.log("ready")
    });
    $("#btn").on('click', function () {
        console.log("click")
    })
});
```

newPageReadyは画面遷移時に発火します。他にもリンククリック時に発火するなど微妙に発火のタイミングが異なるイベントが他に[3つ用意](http://barbajs.org/events.html)されています。

ただ、barba.jsを使った場合、異なる画面をまたいだjavascriptはグローバル変数やセレクターの扱いがかなり繊細になりますので、そこが難点です。

#参考サイト
- [(公式)http://barbajs.org/](http://barbajs.org/)
- [(公式邦訳)http://tr.you84815.space/barba/index.html](http://tr.you84815.space/barba/index.html)
- [https://oku-log.com/pjax-barba/](https://oku-log.com/pjax-barba/)