jQuery で作るシングルページ・アプリケーション(SPA) 70行で動くサンプル付き


※ だいぶ前に書いた記事ですが、未だに見られているようなので、デモページを作って末尾に追記しました。（2020/03/31）

----

こんにちは。jQuery 大好きです。
SPAが気になるこの頃です。

AngularJS や Vue.js を時間のある時にさわって、何とか使えることが分かりホッとしていますが、もっと簡単に使えないものかな、と思っていました。
フレームワークを使うまでもなく、小規模のウェブアプリを、SPAでサクッと作れるようになりたい。

『[ブレイクスルーJavaScript](http://amzn.to/2dC97DR)』を読むと、フレームワークなしでSPAを作る手法が掲載されていました。

なるほど、こういうことか、と合点がいきました。
SPAは、「ハッシュタグを使って、画面遷移を実装する」と理解しました。
AngularJS でもそうでした。
調べたところ、このハッシュタグの取得は、jQuery でも、プラグインを入れれば実装できると分かりました。
※このプラグインは、最新のjQueryで使うためには、多少手を加えるところがありますが、IE6からも対応しています。心強いですね。

以下のサンプルは、ボタン押下で画面遷移を行い、最後の画面に到達したら、ブラウザの「戻る」ボタンを押しても戻れない、というSPAです。
用途として、メールフォームを想定しています。メール送信完了後に、前の画面に戻ってほしくないので。
70行で（ひとつのHTML）で、3画面を表現できます。
2画面目は、ブラウザの「戻る」ボタンで、前に戻ることもできます。

まず、事前処理として、以下のリンクから、jQuery でハッシュタグのイベントを使えるようにするためのプラグインをダウンロードします。
圧縮版でかまいません。
http://www.koikikukan.com/archives/2013/03/22-025555.php
次に、jQuery 1.9系、2系では、以下の変更が必要です。

```html:変更前
$.browser.msie &」
```

```html:変更後
$.support.msie &
```

これだけです。準備OK！

プラグイン導入後は、.hashchange というイベント、ハッシュタグが変更された時のイベントが使えるようになります。
ハッシュタグ自体は、location.hash で取得できますし、これに値を上書きすることができます。

```html:hashchange.js
$(window).hashchange( function(){
    alert( location.hash );
    console.log('ハッシュが変わりました');
});
```

以下が、「最後の画面（完了画面）まで進んだら、戻れない」SPAになります。

```html:spa.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8" />
    <title>Single Page App</title>
<style type="text/css">
.page { display: none; }
</style>
</head>
<body>
    <div id="one" class="page">
        <h1>One</h1>
        <button class="btn" data-hash="two">Twoへ</button>
    </div>
    <div id="two" class="page">
         <h1>Two</h1>
        <button class="btn" data-hash="three">Threeへ</button>         
    </div>
    <div id="three" class="page">
         <h1>Three</h1>
    </div>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script>    
<script type="text/javascript" src="jquery.ba-hashchange.min.js"></script>    
<script type="text/javascript">
$(function(){
    // 初期表示
    if( location.hash === ''){
        displayPage("#one");
    }else{
        displayPage(location.hash);
    }
    // 完了フラグ(falseになったら遷移は不可にする)　
    // 途中でURLを変更しても、falseになっていたら遷移不可
    var completeFlg = true;
 
    // ボタン押下のページ遷移処理
    // ハッシュのみ変更する
    $('.btn').click(function(e){
        e.preventDefault();
        var hash = "#"+$(this).attr('data-hash');
        location.hash = hash;
    });
 
    // ハッシュが変更されたら、そのハッシュに基づいて表示する
    $(window).hashchange(function(){
        if(completeFlg === true){
            clearPage();
            displayPage(location.hash);        
        }else{
            location.hash = "#three";    
            return false;
        }
        if(location.hash === "#three"){
            completeFlg = false;
        }
    });    
 
    // ページ初期化処理
    function clearPage(){
        $(".page").css("display", "none");
    }
    // ページ表示処理
    function displayPage(hash){
        $(hash).css("display", "block");
        // $(hash).fadeIn(2000, "linear"); // アニメーションをつけることも出来る
    }
});    
</script>    
</body>
</html>
```

最初に、ページに相当するDIVをCSSで非表示にしています。
JSでやると、一瞬表示されてから消えるというタイムラグが発生しますので、ここはCSSに任せます。
また、最初のアクセス時には、ハッシュタグがついていないことを想定しています。

『[ブレイクスルーJavaScript](http://amzn.to/2dC97DR)』を読んだなら、もっとこうすればいいのに、など意見がありましたら、ぜひコメントをお願いします。
SPAの構造が理解できたら、jQuery で実装したくなり、やってみた結果が、このサンプルコードになります。

※ デモサイト: https://web-atelier-midori.com/spa/spa.html

※この記事は個人ブログでも掲載しています。http://web-atelier-midori.com/blog/javascript/1681/