LoginSignup
23
19

More than 3 years have passed since last update.

SPAでブラウザバックを使う

Posted at

SPAはブラウザバックが使えない

SPAは1つのHTML内で画面遷移する特性上、SPA内で画面遷移してもブラウザバックで1つ前の画面に戻ることができない。
しかし、ユーザーはそのサイトがSPAなのかなど知るよしもなく、画面遷移してるのにブラウザバックできないのは不便だ。

そこで、どうにかしてブラウザバックを効かせる方法を考えた。

想定する画面遷移ケース

SPA外のページからリンクでSPAに遷移して、その後SPA内で画面遷移することを想定する。

0. SPA外のページ
↓
1. SPAルートページ
↓
2. SPA第2階層ページ
↓
3. SPA第3階層ページ

3まで進んだあと、アプリ内の戻るボタンはもちろん、ブラウザバックでも 3 → 2 → 1 → 0 とSPAの前の画面に戻れるようにしたい。

SPAでブラウザバックを使うコードサンプル

var viewStack = [];

window.addEventListener('popstate', (e) => {
    this.popView();
});

// 画面を追加する
function push(view) {
    if (0 < this.viewStack.length) {
        history.pushState(null, null, view.location);
    }

    this.viewStack.push(view);

    // TODO viewを画面に表示する
}

// 前の画面に戻る
function pop() {
    history.back();
}

function popView() {
    if (this.viewStack.length === 1) {
        return;
    }

    this.viewStack.pop();

    // TODO 一つ前のviewを画面に表示する
}

push の引数のviewは画面を表すインスタンスで、HTMLのelementとURLになるlocationを持っている想定。
画面の表示を切り替える処理などは省略して TODO にしている。

ポイントと解説

window.addEventListener

window.addEventListener('popstate', (e) => {
    this.popView();
});

addEventListener の最初の引数を'popstate' にすると、ブラウザバックのイベントをフックすることができる。
このコードによりブラウザバックが押されたら popView() が呼ばれ、SPA内で一つ前の画面に戻ることができる。

ブラウザバックした画面がSPAのルートページなら、ブラウザが勝手に前画面に戻してくれるのでSPA側で何もする必要はない。
ルート画面でない場合はブラウザバックしてもURLが変わるだけで、ブラウザは画面を切り替えないので、popView() 関数でSPA内のページバックを行う。

history.pushState

if (0 < this.viewStack.length) {
    history.pushState(null, null, view.location);
}

history.pushStateで履歴を追加できるので、SPAで画面を追加するときにpushStateを呼び出してやる。
3つ目の引数はURLのパスで、指定した値はブラウザのアドレスバーに反映される。

ここでのポイントは if (0 < this.viewStack.length) で、ルート画面を表示するときは pushStateを呼ばないことだ。
外部ページからSPAのルート画面に遷移するときは既にブラウザによって履歴が追加されているので pushState を実行すると履歴が2重に追加されてしまう。

history.back

// 前の画面に戻る
function pop() {
    history.back();
}

SPA内の「戻る」ボタンで前の画面に戻る場合、history.back() を呼び出せば addEventListener で登録したコールバックが実行され、前の画面に戻ることができる。

おわりに

Chrome、Safariで思ったとおりに動くことは確認したが、本番プロダクトで試したことのない実装なので、何か問題があれば教えて欲しい。

23
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
19