ons-navigatorによるページのスタック管理について

  • 2
    いいね
  • 0
    コメント

Onsen UI Advent Calendar 2016 23日目の記事です。

Onsen UIでは、<ons-navigator> というコンポーネントを使ってネイティブアプリのようなアニメーション効果つきの画面遷移を実現することができます。
今回は <ons-navigator> の使い方について掘り下げて紹介します。

ページ管理のしくみ

<ons-navigator> には、代表的な2つのメソッドがあります。

  • pushPage() 次のページへ進む
  • popPage()  前のページへ戻る

内部的には、以下の図のようにページがスタック状に積み重ねられて管理されています。

navigator1.png

ページA → ページB → ページA → ページB → ページA → ページB といったように、2つのページを何度も行き来したい場合、通常は pushPage()popPage() を交互に実行します。
しかしアプリの要件として、次のページへ進むアニメーション(現在のページの上に遷移先ページが重なる動き)で遷移したい場合もあると思います。
そのときにpushPage() だけを使って画面遷移を行うのは好ましくありません。
pushPage() を使い続けていると、スタック上に大量のページが積み重なっていくことになり、最終的にメモリリークが発生する危険があるためです。
仮に pushPage("pageB.html") を5回実行すると、スタックには5つのページが蓄積されます。同一のHTMLファイルであったとしてもページのインスタンスは新しく生成されるという点がポイントです。

ではどうするかというと、bringPageTop() を使います。bringPageTop() は、指定したページをスタックの一番上に移動する命令です。

navigator2.png

(もしスタック内に指定したページが存在しない場合は、新しく生成されます)

また、よくある画面遷移の例として、TOP → 一覧画面 → 詳細画面 → 編集画面 → 完了画面 → TOP といったように、複数のページを経て最初のページに戻る場合があります。
こういった場合は、スタックに無駄なページが溜まらないように、TOPページに戻ったときにスタック内のすべてのページを消去しましょう。
resetToPage() というメソッドを使うと、指定したページに遷移した後にスタックがリセットされます。使い方は以下のようになります。

document.getElementById("navigator").resetToPage("top.html", {animation:"default"});

※ resetToPage() は、デフォルトではアニメーションがつかないため、第二引数にアニメーションの種類を指定します。

その他にも、スタック内にページを挿入する insertPage() や、 スタック内のページを指定したページに置き換えるreplacePage() などのメソッドがあります。

またメソッドとしては用意されていませんが、ons-navigator の pageLoaderプロパティ(ページスタック)と pagesプロパティ(スタック内のページ配列)を使うことでスタック内のページを削除することもできます。

たとえば以下の図のように 一覧画面 → 検索画面 → 編集画面 と遷移し、編集画面で更新をした後は検索画面をスキップして一覧画面に戻りたい、といった場合、スタックから一つ前のページを削除した後に popPage() を実行します。

navigator3.png

編集画面で更新処理完了後の処理
var navi = document.getElementById("navigator");
// 検索画面を削除
navi.pageLoader.unload(navi.pages[1]);
// 前のページに戻る
navi.popPage();

なお、pageLoader.unload() は Onsen UI 2.0.5 から追加された機能です。以前のバージョンでは利用できないので注意してください。

まとめ

今回は <ons-navigator> によるページ管理の内部構造について説明しました。見た目上は問題なく動作していても、裏側ではスタックに大量のページが溜まっているケースがあります。アプリを使い続けているうちにパフォーマンスが低下してきたという場合、一度見直してみると良いでしょう。