NativeScriptのGetting Startedを試してみる（２

http://docs.nativescript.org/hello-world/hello-world-ns-cli.html#4-explore-the-newly-created-project

[前回](http://qiita.com/kazusa-qooq/items/04c3228a135152b47ec9)に続いてAndroid, iOS, Windows Phoneのアプリをjavascriptで書けるNativeScriptのGetting Startedを試していきます。サンプル画面が表示できたところからです。プロジェクトは以下のようになっています。

```
└── hello-world
    ├── app
    │   ├── app
    │   │   ├── app.css
    │   │   ├── app.js
    │   │   ├── bootstrap.js
    │   │   ├── main-page.js
    │   │   └── main-page.xml
    │   ├── App_Resources
    │   │   └── ...
    │   └── tns_modules
    │       └── ...
    └── platforms
        └── ...
```
* app 以下が我々の開発スペースである。
* platforms は初期状態では空。platform add すると追加される。ビルド用のリソースが格納される。このディレクトリは変更してはならない。
* app/App_Resourcesはプラットフォームによって異なる個別のリソースを格納する。アイコンやスプラッシュシートなどが含まれる。
* app/tns_modules にはNativeScriptモジュールが格納される。カメラやロケーションなどのプラットフォームの機能を提供する。
* app/app/app.jsがアプリの開始点になる。サンプルではmain-pageをmainModuleに設定している。これはmain-page.jsとmain-page.xmlにコントロールを渡している。

#Build Something Awesome
タスクマネージャを作成します。
![image](https://qiita-image-store.s3.amazonaws.com/0/71988/afe2a73a-bee1-43af-cb01-878d4eaf8b09.png)
目的は以下を理解することです。

* UIの構築方法
* ＭＶＶＭの実装方法
* ＣＳＳによるスタイリングの仕方

##1. Add user interface
NativeScriptではUIの定義にXMLを用います。いまは`app/main-page.xml`の１ページのみです。同じディレクトリに`tasks.xml`を作成しましょう。

``` app/tasks.xml
<Page loaded="onPageLoaded">
    <GridLayout rows="auto, *">
        <StackLayout orientation="horizontal" row="0">
            <TextField width="200" text="{{ task }}" hint="Enter a task" id="task" />
            <Button text="Add" tap="add"></Button>
        </StackLayout>

        <ListView items="{{ tasks }}" row="1">
            <ListView.itemTemplate>
                <Label text="{{ name }}" />
            </ListView.itemTemplate>
        </ListView>
    </GridLayout>
</Page>

```
ここでNativeScriptのレイアウトメカニズムが登場します。GridLayout と StackLayoutです。ここではGridLayoutで画面を上下に２分しています。
StackLayoutは名前の通り、縦か横にものを積むレイアウトです。例では横向きにテキスト欄とボタンを並べています。
そのほかのレイアウトについては http://docs.nativescript.org/layouts.html を参照ください。
だいたい察しがついていると思いますが、XML内の`"{{ name }}"`などはデータバインディングです。どのように働くかは次項で確認します。

##2. Create the view model
NativeScriptのフレームワークはＭＶＶＭパターンに従って最適化されています。これはデータとＵＩを同期させるエレガントな手法だそうです。`app/tasks.js`ファイルを作り、その働きを見てみましょう。

``` app/tasks.js
var observableModule = require("data/observable");
var observableArray = require("data/observable-array");
var viewModule = require("ui/core/view");

var tasks = new observableArray.ObservableArray([]);
var pageData = new observableModule.Observable();
var page;

exports.onPageLoaded = function(args) {
    page = args.object;
    pageData.set("task", "");
    pageData.set("tasks", tasks);
    page.bindingContext = pageData;
};

exports.add = function() {
    tasks.push({ name: pageData.get("task") });
    pageData.set("task", "");
    viewModule.getViewById( page, "task" ).dismissSoftInput();
};
```

exportsがあるのでわかると思いますが、Node.jsのモジュールとしてjsファイルを作成してます。この例ではonPageLoaded と add の２つのメソッドが定義されており、それらはviewのxmlに渡されます。xmlを見るとPageとButtonタグでそれぞれが呼び出されているのがわかると思います。

次に重要なのがonPageLoaded内にある`page.bindingContext = pageData`です。これはバインディング用のオブジェクトとしてpageDataを設定しています。これによりview側で`{{ }}`を使用してpageDataのプロパティにアクセスすることができます。たとえばpageDataのtasksにアクセスするなら`{{tasks}}`でアクセスできます。

MVVMアプローチの最大の利点は、データの変更に応じてビューが更新される点です。addメソッド内でtasksにタスクが追加されています。tasksはObservableであり、viewのListViewにバインドされているため、addメソッドが実行されると自動的にListViewの表示が更新されます。

これによりコードが簡潔になり、ロジックとビューが疎結合になります。この例だとjsはバインディングされるviewを気にする必要がありません。

##3. Style your app
ではCSSを使って見た目をよくしましょう。
xmlと同名のCSSが自動的にロードされます。
またapp.cssは全ページに適応されます。少しタスクマネージャにスペースを設けるために、app.cssを以下のように変更しましょう。

``` app/app.css
label {
    margin: 15;
}
textfield {
    margin: 15;
}
```

##4. The finishing touches
ではタスクマネージャをアプリの開始点に設定し、アプリを起動しましょう。エラーが出る場合はファイル名が間違ってる可能性が高いです。見直しましょう。

``` app/app.js
var application = require("application");
application.mainModule = "app/tasks";
application.start();
```

``` 起動.
tns run android --emulator
```

うまくいけば以下のようなアプリが起動します。
[原文](http://docs.nativescript.org/hello-world/hello-world-ns-cli.html#4-the-finishing-touches)のほうにGIFもあります。
![image](https://qiita-image-store.s3.amazonaws.com/0/71988/afe2a73a-bee1-43af-cb01-878d4eaf8b09.png)

#Move Beyond the Basics
以上でGetting Startedは終了になります。なかなか便利そうですね。