clover.blue

pushStateとAjaxの組み合わせpjax

Data
2019/09/16
Tag

site: http://develo.org/2014/04/29/1614.html

サイトをpjaxを使って実装して思ったのですが、ページ移動がものすごくはやくて快適!今後サイト新しく作るときはpushStateとAjaxの組み合わせ検討してみてもよいかなぁって思いました!

pushStateとは

Ajaxなどで、非同期なサイトを作る際に、
アドレスが変更されない問題をjsで解消してくれる便利なやつです。
少し前の話だとFlashサイトを作るときに#(ハッシュ)をつけてurlを管理したりしていました。
pushStateを使うと普通にページ遷移しているようにアドレスを変更することができます!

Ajaxとは

ページを遷移せずに情報だけを非同期でとってきてサイトに描画する仕組みのことです。

pjax

pushStateとAjax 2つを合わせてつくった仕組みのことです。

実際に作るにあたり

下記を参考にさせていただきました。
jquery-pjaxというプラグインを使うと簡単に実装することができます。

使い方

下記のような感じで実行するだけで実装できます。

$(document).pjax('a', {
    container:'main',  // 現在のページの置き換えたいエリアのタグを指定
    fragment: 'main', // 読み込み先ページの置き換えたいエリアのタグを指定
    timeout: 30000 // タイムアウトする時間(タイムアウトした場合は通常のリンクでの移動になります。)
});

このコードは「a」タグをクリックした時に現在のページのmain要素部分を、読み込み先のhtmlのmain要素に置き換える。といった動きになります。

timeoutを設定しているのはプラグインの初期のtimeout設定が650msと少し短いため3秒はtimeoutしないように指定しなおしています。

ローディング時の処理をする。

pjax:send

ajaxの処理が始まった時点で実行されます。
この時にローディング時の処理をかきます。

$(document).on('pjax:send', function(e) {
    $('body').addClass('loading');
});

pjax:complete

ajaxの処理が終わった時点で実行されます。ローディングが終わった時の処理をかきます。

$(document).on('pjax:complete', function(e,data) {
    $('body').removeClass('loading');
});

こんな感じで書くと実装できるので、割と簡単ですね!

応用

CSSシグネチャを使っている場合の対処法

CSSシグネチャというのはbodyにclassやidをつけてcssで管理する方法です。

pjaxのプラグインを使うと指定エリア外のbodyのclassやidは変更してくれません。そのためページごとのCSSが反映されないという現象がおきてしまいます。

解決方法 : pjax:complete時にbodyの属性を変更する

読み込み先のテキスト情報を元に、範囲指定して特定のテキストを取得する正規表現を使いbodyの情報を変更します。(特定の文字列から文字列の範囲内の文字を取得する正規表現

RegExp.$1で最初にマッチした値を取ってくることができます。

$(document).on('pjax:complete', function(e,data) {
    var data = data.responseText;   //2つ目の引き数のresponseTextの中身に読み込みさきのtextデータが含まれています。

    //responseTextの内容を正規表現を使うことによりbodyのclassとidを変更する。
    //bodyのID
    data.match(/id="([^\"]+)/);
    var value = RegExp.$1;
    $('body')[0].id = value;
    //bodyのClass
    data.match(/class="([^\"]+)/);
    value = RegExp.$1;
    $('body')[0].className = value;
});

こんな感じでプラグインで指定した範囲以外のタグも変更することができます。これを使
えば、keywordsやdescriptionやogタグを変更することもできます。

ブラウザバック時の再読み込み

ブラウザバック時にcssシグネチャを使っていると同じ現象がおきてしまいます。

なので・・どうしようと迷ったのですが・・。

ブラウザバック時、キャッシュを読みにいく処理が入っているようで、その部分を変更しブラウザバック時にも再度読み込み直すようにプラグイン事態を変更しちゃいました。何か他にプラグインを変更せずにすめば良いと思ったのですが・・。

440 〜 450行目あたりをコメントアウトして変更しちゃいます。

/*
    if (contents) {
        container.trigger('pjax:start', [null, options, contents])

        if (state.title) document.title = state.title
        container.html(contents)
        pjax.state = state

        container.trigger('pjax:end', [null, options, contents])
    } else {
        pjax(options)
    }
*/
pjax(options)

こんな感じでキャッシュがある場合はキャッシュを使って変更している部分を毎回読み込むように変更しちゃいます!

これでひと通りCSSシグネチャを使った場合でもpjaxプラグインで実装することができました!