ionic2でハイブリッドなアプリ開発:チュートリアルをチュートリアル:サンプルプロジェクトを導入して実機で実行するまでこの記事の通りですが、とりあえずionic2のサンプルをそのままならば実行できる状態になりました。が、もちろんそれでは何も面白くありませんので、チュートリアルの本編を敷衍して、アプリ開発の流れを俯瞰します。なお可能であれば以下のionicチームによるAngular2の解説を読んでおくと、よりスムーズに理解できると思います。が、たぶん読まなくても何とかなります。Learn Angular 2 · Learn Angular 2
プロジェクトフォルダの作成
まずプロジェクトのフォルダを作成します。前回、紛らわしいのは避けるようにと書いたくせに、project2と付けてしまいました。tutorialとなっている引数は、プロジェクトのテンプレートを指定する部分です。tutorialは公式が提供しているionic2のチュートリアルのためのテンプレートです。何も指定しない場合には、tabs starterテンプレートが使用されます。
$ ionic start project2 tutorial --v2
このとき–tsオプションを付けるとTypeScript用の構成となります。typingsフォルダがあったり、tsconfig.jsonの中身が違ったりと、若干構成が変わるようです。プロジェクトフォルダに移動してionic serveするとブラウザでテンプレートの動作を確認できます。
$ cd project2$ ionic serve
ちなみにですが、ionicには公式IDEは無いようですが、オススメ環境はあるようです。Ionic 2 Resources | Editors and IDEs – Ionic 2 Developer Preview – Ionic Framework私はもともとatomを使っていたのですが、さらにオススメとあれば使わない手はありません。atomで環境を構築する事にします。コードハイライタや補完機能はもともと備わっているので、とりあえずbrowser-plusを入れて、全画面表示でコードとブラウザの両方を同時に見られるようにしてみました。Terminal-Plusも入れているので、ターミナルも同一画面内で操作できます。これでmonacaのcloudIDEっぽくなりました。
フォルダ・ファイル構成
ionic startを実行してできあがるフォルダツリーはCordovaの標準的な構成らしいです。そのためCordvaプラグインをインストールすることができますし、プラットフォーム特有のファイルを置くこともできます。www/index.htmlがアプリの一応のエントリポイントです。
アプリに必要となるスクリプトをこのHTMLから読み込みます。ですが、このファイルはcssを読み込んだり、bootstrapを読み込んだりするためだけのものに過ぎません。ionicの開発でこのファイルをいじることは少ないようで、実際にはapp/app.jsをエントリポイントとして扱います。ionic開発ではこのappフォルダにコンパイル前のコードが収蔵されていて、作業の中心的な場所になります。このフォルダ内のコードはionic serveの実行時にトランスパイルされるので、appフォルダではES6やTypescriptが使用できます。app.jsのMyAppクラスには以下のデコレーターが付いています。すべてのionicアプリケーションはルートになるコンポーネントを持ちますが、Appデコレーターを付けるとルートと扱われます。指定されているtemplateUrlがbuildフォルダになっていますが、このファイルはapp/app.htmlがビルド時にコンパイルされたものなので、編集する際にはapp/app.htmlを編集します。
@App({ templateUrl: 'build/app.html', config: {} // http://ionicframework.com/docs/v2/api/config/Config/})
app.htmlテンプレートの構成
このファイルには、ion-menuタグとion-navがあります。コード量ではion-menuの占める割合が大きいですが、これはハンバーガーアイコンをクリックして引き出されるメニューを記述しています。そのためion-menuの記述内容は最初は一切画面に表示されていません。
Pages
id属性で指定されている名前は、後でこのコンポーネント(ion-menuとかion-navのひとまとまり)をgetComponent関数で指定するために使用します。
Menus
起動直後の画面では、Menusを使っています。Menus : ionic 2 Components – Ionic 2 Developer Preview – Ionic FrameworkMenusでメニューを記述するためにはion-menuを、メニューからナビゲートされるページにはion-navを指定します。ion-menuにはcontent属性があります。これはどのコンテンツで画面がドラッグされたときに、メニューを開閉させるかを指定するところです(メニューにとってのメインコンテンツはどれか)。両方contentなのでややこしいですが、左側のオレンジのcontentがion-menuの属性です。[]で囲むと、Angular2の機能によってバインディングされ、代入された内容に追随するようになります。代入されているcontentはローカル変数です。ion-navの方に#contentと指定されているのが分かると思いますが、これはAngular2におけるローカル変数の指定で、ローカル変数であるcontentにion-navが代入されたことになります。結果、ion-menuのcontentにはこのコードの下部のion-navが代入された事になります。*ng-forはAngular2のディレクティブで配列をイテレートします。ここではpages配列を順番にpに代入しながら配列の最初から最後まで繰り返しを行います。(click)もAngular2のディレクティブで、要素がクリックされたときに指定された関数を実行します。app.js内にopenPage関数が定義されていて、開いているメニューを閉じてからsetRootでnavのページを変更しています。{{p.title}}はDIによって変数がレンダリングされる部分です。これは後で解説します。
ion-nav
ページ本文がion-navの方です。中身が無いのは、root属性で指定されたページがロードされるからです。Navigation : Ionic 2 Components – Ionic 2 Developer Preview – Ionic Framework[root]もバインディングでrootPageが指定されています。これはapp.jsのthis.rootPage変数です。この変数にはHelloIonicPageが代入されています。
import {HelloIonicPage} from './pages/hello-ionic/hello-ionic';
HelloIonicPageには冒頭部で./pages/hello-ionic/hello-ionicがインポートされています。インポートしているのはhello-ionic.jsです。
@Page({ templateUrl: 'build/pages/hello-ionic/hello-ionic.html'})export class HelloIonicPage { constructor() { }}
すべてのページはこのようにクラスとコンパイル後のテンプレートで構成されます。build/pages/hello-ionic/hello-ionic.htmlの実体はapp/pages/hello-ionic/hello-ionic.htmlなのでここにページの内容が記述されています。tutorialのapp以下のフォルダ・ファイル構成は、フォルダ名と同名のhtml/js/cssとなっています。これはionicにとって必須のものでは無いものの、ファイルをきちんと整理する観点から推奨されるとのことです。
Page
Pageデコレーターはインポート元であるnode_modules/ionic-framework/decorators/page.jsに実装されています。ここはフレームワーク部分ですからユーザーが触ることはありません。Page – Function in module – Ionic FrameworkPageデコレーターが付けられると、Angularのビューとして構成されるので、セレクタを使わなくても動的に内容が変更できるページになります。PageはNavControllerによりナビゲーションをさせることができます。
Hello I test
Welcome to your first Ionic app!
This starter project is our way of helping you get a functional app running in record time.
Follow along on the tutorial section of the Ionic docs!
一見して、ブラウザに最初表示された内容であることがわかると思います。上部の表示が変なのは私がコードを適当にいじったからです。ただ適当にいじったとおりに表示が変わっているのが分かると思います。Pageのテンプレートはデコレータのところで直接記述することもできます。が、ビューの分離や可読性の向上の観点からすると分離をすべきでしょう。
Live reload
ここでコードを書き換えてみます。この変更をして保存をした後、5秒ほどすると、ブラウザが自動的にリロードされ、ブラウザに表示されている内容が書き換わっています。ターミナルのionic serveが作動していることが条件ですので、上手く変更されない場合には、ターミナルの動作状況を確認してください。変更時にはionic serveが変更を捕捉したことがターミナルに出力されています。
ionic $ ∆ Copying HTML√ Matching patterns: app/**/*.html√ HTML copied to www/buildHTML changed: www/build/pages/hello-ionic/hello-ionic.html
ion-navbar
hello-ionic.htmlの下記の部分(ion-navbar)は、画面上部に表示されているハンバーガーアイコンとタイトルを記述しています。この中にion-nav-itemsやion-titleを記述して、その時々に応じたバーを表示させます。
Hello ionic
この中の「*navbar」は現状効能が不明です。削除してもサンプルはそのまま動作しました。buttonにmenuToggleというキーワードが入っています。これはionicが備えているディレクティブで、ボタンにメニューをトグルする機能を持たせることができます。MenuToggle – Class in module – Ionic Frameworkion-contentが本文部分ですが、この中のbuttonもmenuToggleが記述されているのでメニューをトグルします。
NavController
サイドメニューでMy First Listをタップするとpagesのcomponentで指定されているListPageに遷移します。ListPageは./pages/list/listからインポートされていますので./pages/list/list.jsのクラスです。
import {Page, NavController, NavParams} from 'ionic/ionic';import {ItemDetailsPage} from '../item-details/item-details';@Page({ templateUrl: 'build/pages/list/list.html'})export class ListPage { constructor(nav: NavController, navParams: NavParams) { this.nav = nav; // If we navigated to this page, we will have an item available as a nav param this.selectedItem = navParams.get('item'); this.icons = ['flask', 'wifi', 'beer', 'football', 'basketball', 'paper-plane', 'american-football', 'boat', 'bluetooth', 'build']; this.items = []; for(let i = 1; i < 11; i++) { this.items.push({ title: 'Item ' + i, note: 'This is item #' + i, icon: this.icons[Math.floor(Math.random() * this.icons.length)] }); } } itemTapped(event, item ,index) { this.nav.push(ItemDetailsPage, { item: item }); }}
ionicのNavigationはページ間に親子関係があるページナビゲーションを実現するためのコンポーネントです。NavControllerをコンストラクタで変数にバインドすれば、コード内でNavControllerを使用できるようになります。Navigation : Ionic 2 Components – Ionic 2 Developer Preview – Ionic Frameworkページ同士の関係はスタックになっているので、NavControllerでpushすればページを追加して遷移、popをすれば今のページを取り除いて下のページに戻ります。list.htmlのbuttonのclickにitemTapped関数が指定されています。クリックするとItemDetailsPageにpushされて遷移します。コンストラクタの中はhtmlで使用するitem配列を作成しています。乱数で生成されているので、このコンストラクタが呼ばれる度(ページに来る度)にアイコンが変わります。なおこのコードには下記の下線部のコードがありますが、使用していません。次のコードの関係でゴミが残ってしまったのでしょう。
DIを体験してみる
せっかくなのでここでDIの実験をしてみたいと思います。list.htmlの10行目の以下の様に書き換えます。ngforの実行時に変数iにインデックス番号を代入し、クリック時に実行される関数にインデックス番号を引数として渡します。
list.jsの28行目以降を以下の様に書き換えます。もともとのpushをコメントアウトして、items配列の要素のtitleを書き換えます。
itemTapped(event, item ,index) { this.items[index].title = 'pushed'; /* this.nav.push(ItemDetailsPage, { item: item });*/ }
これによりタップしたリストアイテムのtitle部分がpushedに書き換わりました。ポイントはjsのロジック上は、ビューの要素を変更する処理を行っていないということです。ただitemsの各要素はリストの要素にバインドされているので、itemsの個別の変数を変更すれば、それによって作られたリストの中身が自動的に変更されます。
NavParams
ItemDetailsPageは../item-details/item-detailsからインポートされていますので、中身はitem-details.jsです。
import {Page, NavController, NavParams} from 'ionic/ionic';@Page({ templateUrl: 'build/pages/item-details/item-details.html'})export class ItemDetailsPage { constructor(nav: NavController, navParams: NavParams) { this.nav = nav; // If we navigated to this page, we will have an item available as a nav param this.selectedItem = navParams.get('item'); }}
ここでのポイントはNavParamsです。NavParamsはデータを保持できるオブジェクトです。NavParams – Class in module – Ionic Framework一つ前のlist.jsのitemTapped関数内のpushでitemという引数を渡しています。pushはページを移動するだけで無く移動先のページに対して、パラメーターを渡すことができます。NavController – Class in module – Ionic Frameworkこの場合でいくとlist.js内のitemをitemというラベルを付けて、次のページに渡すということです。そして次のページではNavParamsを使って、navParams.get(‘item’)と指定することで渡されたデータを取得できます。this.nav = nav;は無意味な記載でコメントアウトしてもちゃんと動作します。
Item Details
取得されたデータはselectedItemに代入されており、まず*ngIfでの表示のコントロールに使用されています。当然selectedItemは中身があるのでdivが表示され、タイトルがレンダリングされます。
チュートリアル完了
チュートリアルはここで完了です。今後は以下のコンテンツを参照して欲しいとのこと。Platform sectionとDeveloper resources section へのリンクもありましたが、リンク切れでした。Ionic 2 Components – Ionic 2 Developer Preview – Ionic FrameworkIonic Forum #ionic2 #初心者 #入門 #チュートリアル #解説 #TypeScript #Angular2″””