Help us understand the problem. What is going on with this article?

Onsen UI初心者がハマりがちなポイント(SPAについて)

More than 3 years have passed since last update.

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

Onsen UI ではSPAという仕組みが採用されています。Onsen UIで複数ページから構成されるアプリを作成する場合、SPAについての理解は必須です。そこで今回はSPAについて解説します。

SPAとは

SPAは、「Single Page Application」の略で、その名の通り単一のWebページによって構成されるアプリのことを指します。
アプリ起動時に全ページのリソース(HTMLファイル、CSSファイル、JavaScriptファイル)がロードされ、ページの切り替えはDOM操作によって行われるため、ストレスのない高速な画面遷移を実現できることが最大のメリットであると言えます。

Onsen UIによるSPAの構築

Onsen UIでは、index.html の中に各ページが埋め込まれる構成となっています。
各ページは異なるHTMLファイルに分割して記述しても良いですし、index.htmlの中にまとめて記述しても良いです。
以下のコードは、どちらも同じことを行っています。

ファイルを分割して記述

index.html
<!DOCTYPE HTML>
<html>
<head>
  <!-- 各メタデータ要素は省略 -->
</head>
<body>
  <ons-page>
    <ons-toolbar>
      <div class="center" id="toolbar-title"></div>
    </ons-toolbar>
    <ons-tabbar position="auto">
      <ons-tab label="Tab 1" page="tab1.html" active>
      </ons-tab>
      <ons-tab label="Tab 2" page="tab2.html">
      </ons-tab>
    </ons-tabbar>
  </ons-page>
</body>
</html>
tab1.html
<ons-page id="first-page">
  <p>
    This is the first page.
  </p>
</ons-page>
tab2.html
<ons-page id="second-page">
  <p id="message">
    This is the second page.
  </p>
</ons-page>

index.html内にまとめて記述

index.html
<!DOCTYPE HTML>
<html>
<head>
  <!-- 各メタデータ要素は省略 -->
</head>
<body>
  <ons-page>
    <ons-toolbar>
      <div class="center" id="toolbar-title"></div>
    </ons-toolbar>
    <ons-tabbar position="auto">
      <ons-tab label="Tab 1" page="tab1.html" active>
      </ons-tab>
      <ons-tab label="Tab 2" page="tab2.html">
      </ons-tab>
    </ons-tabbar>
  </ons-page>

  <ons-template id="tab1.html">
    <ons-page id="first-page">
      <p>
        This is the first page.
      </p>
    </ons-page>
  </ons-template>

  <ons-template id="tab2.html">
    <ons-page id="second-page">
      <p id="message">
        This is the second page.
      </p>
    </ons-page>
  </ons-template>
</body>
</html>

<ons-page> がページを定義するタグ、 <ons-template> が仮想的なHTMLファイルを定義するタグです。

さて、ここから先がはじめてOnsen UIを使う人がハマりがちなポイントです。
Tab2が開いたときに、ページ内の要素をDOM操作したいといった場合、以下のように書くのは誤りです。

誤った例

index.html
<!DOCTYPE HTML>
<html>
<head>
  <!-- 各メタデータ要素は省略 -->
</head>
<body>
  <ons-page>
    <ons-toolbar>
      <div class="center" id="toolbar-title"></div>
    </ons-toolbar>
    <ons-tabbar position="auto">
      <ons-tab label="Tab 1" page="tab1.html" active>
      </ons-tab>
      <ons-tab label="Tab 2" page="tab2.html">
      </ons-tab>
    </ons-tabbar>
  </ons-page>

  <ons-template id="tab1.html">
    <ons-page id="first-page">
      <p>
        This is the first page.
      </p>
    </ons-page>
  </ons-template>

  <ons-template id="tab2.html">
    <ons-page id="second-page">
      <p id="message">
        This is the second page.
      </p>
    </ons-page>
  </ons-template>

  <!-- tab2.htmlに対するDOM操作 -->
  <script>
    document.getElementById("message").textContent = "Tab2が開きました";
  </script>

</body>
</html>

<body> 内の一番下に <script> タグを書いているのに getElementById() で要素が取得できない!と思うかもしれません。

各ページに対してDOM操作やイベント登録などを行う場合は、ページが初期化されたタイミングで発生する init イベントを使うのが適切です。

正しい例

index.html
<!DOCTYPE HTML>
<html>
<head>
  <!-- 各メタデータ要素は省略 -->
  <script>
    document.addEventListener("init", function(event) {
        var page = event.target;  // initイベントが発生したページ
        if(page.id === "second-page") {
            // tab2.htmlに対するDOM操作
            document.getElementById("message").textContent = "Tab2が開きました";
        }
    });
  </script>
</head>
<body>
  <ons-page>
    <ons-toolbar>
      <div class="center" id="toolbar-title"></div>
    </ons-toolbar>
    <ons-tabbar position="auto">
      <ons-tab label="Tab 1" page="tab1.html" active>
      </ons-tab>
      <ons-tab label="Tab 2" page="tab2.html">
      </ons-tab>
    </ons-tabbar>
  </ons-page>

  <ons-template id="tab1.html">
    <ons-page id="first-page">
      <p>
        This is the first page.
      </p>
    </ons-page>
  </ons-template>

  <ons-template id="tab2.html">
    <ons-page id="second-page">
      <p id="message">
        This is the second page.
      </p>
    </ons-page>
  </ons-template>
</body>
</html>

SPAとして構築されているために、ページが初期化されるタイミングが通常のWebアプリとは異なるのですね。
JavaScriptを書く場所がわからない!と悩んだ方の参考になれば幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした