Cordovaのチュートリアルをやってみる 第八回

# 使用したもの(環境)
 1. cordova
 1. visualStudioCode
 1. windows10
 1. Android
 

---

# チュートリアルを訳しながらやってみる
チュートリアルのページは下記。

[Module 9: Creating Views](http://ccoenraets.github.io/cordova-tutorial/creating-view-classes.html)

前回のチュートリアル。

[Cordovaのチュートリアルをやってみる 第七回](https://qiita.com/tokky_se/items/ba37ffcbb4fc2c28369a)

環境構築については別途まとめてあるので下記参照。

[cordova&VSCodeで環境を構築するまでの右往左往メモ。](https://qiita.com/tokky_se/items/346429d234c91bece11d)

---


# Module 9: Creating Views

It's time to provide the application with some structure.   
アプリケーションに何らかの構造を与えましょう。

If we keep adding all the core functions of the application to the immediate function that bootstraps the app,   
アプリケーションをブートストラップする即時関数にアプリケーションのすべてのコア関数を追加し続けることで、

it will very quickly grow out of control.   
制御が非常に迅速になるでしょう。

In this section we create a HomeView object that encapsulates the logic to create and render the Home view.  
このセクションでは、ホームビューの作成とレンダリングするロジックをカプセル化するHomeViewオブジェクトを作成します。

1\. jsディレクトリにHomeView.jsという名前のファイルを作成し、次のように実装されたHomeViewコンストラクタを定義します。  
コンストラクタ関数は、従業員データサービスを引数として取ります。
具体的に言うと、EmployeeServiceのことです。(チュートリアルにはEmployeeService.jsに複数の実装があるので、どの実装かはhtmlに記載したものによります)

```js  
var HomeView = function (service) {

}
```

2\. HomeViewは、ネストされたビューを使用して従業員のリストを表示します。  
従業員のリストを別個のビューとして定義すると、他のコンテキストで再利用できるようになります。  
以下のステップ2でEmployeeListViewを定義します。  
今のところ、ネストされたビューを追跡するためのローカル変数を定義します。

```js  
var HomeView = function (service) {    
    var employeeListView;
}
```

3\. HomeViewコンストラクタ内でinitialize関数を定義します。
 * ビューのdivラッパーを定義します。divラッパーは、ビュー関連のイベントをアタッチするために使用されます。
 * ネストされたビューをインスタンス化します（手順2でEmployeeListViewを定義します）。
 * 最後に、HomeViewコンストラクタ関数内でinitialize（）関数を呼び出します。

```js  
var HomeView = function (service) {

    var employeeListView;

    this.initialize = function () {
        // Define a div wrapper for the view (used to attach events)
        this.$el = $('<div/>');

        // this.findByNameはEmployeeService.jsの関数。
        // それをイベントとして設定する。
        this.$el.on('keyup', '.search-key', this.findByName);
        employeeListView = new EmployeeListView();

        // ここのrenderは次の項目で定義するrender
        this.render();
    };

    this.initialize();

}
```

4\. renderHomeView関数をapp.jsからHomeViewクラスに移動します。  
ビューを再利用できるようにするには、HTMLをドキュメント本体の代わりにdivラッパー（this.el）に添付します。  
この関数はHomeViewでカプセル化されているので、renderHomeViewからrenderにリネームすることもできます。

>>この関数はHomeViewでカプセル化されているので、renderHomeViewからrenderにリネームすることもできます。  
という表現がしっくりこないのは私だけでしょうか？  
app.jsから隠蔽されているという意味ではその通りなのですが…。  
別にapp.jsに合ってもリファクタリングする障害とはなりえないと思えるからでしょうか。

また、renderHomeViewはあとで削除する手順が別途記述されているので、  
app.jsのコードをコメントアウトするなどはちょっと後回しにしてください。

```js  
this.render = function() {
    this.$el.html(this.template());
    $('.content', this.$el).html(employeeListView.$el);
    return this;
};
```

5\. findByName（）関数をapp.jsからHomeViewに移動し、ネストされたビューで動作するように調整します。  
こちらもコメントアウトなどするのは後回しにしてください。

```js  
this.findByName = function() {
    service.findByName($('.search-key').val()).done(function(employees) {
        employeeListView.setEmployees(employees);
    });
};
```

ステップ2 EmployeeListビューを作成する
1\. jsディレクトリにEnployeeListView.jsという名前のファイルを作成します。

2\. EmployeeListViewを次のように実装します。

```js  
var EmployeeListView = function () {

    var employees;

    this.initialize = function() {
        this.$el = $('<div/>');
        this.render();
    };

    this.setEmployees = function(list) {
        employees = list;
        this.render();
    }

    this.render = function() {
        this.$el.html(this.template(employees));
        return this;
    };

    this.initialize();

}
```

ステップ3 ホームビューを使用する
1\. index.htmlにEmployeeListView.jsとHomeView.jsのスクリプトタグを追加しましょう。 (app.jsのスクリプトタグより前に書いてください。)

```html  
<script src="js/EmployeeListView.js"></script>
<script src="js/HomeView.js"></script>
```

2\. app.jsからrenderHomeView関数を削除します。

3\. app.jsからfindByName関数を削除します。

4\. テンプレートの初期化を変更します。ローカル変数として宣言する代わりに、それぞれのクラスのプロトタイプに追加します。  
深く考えず、HomeViewとEmployeeListViewそれぞれのプロパティとしてtemplateを持ちたいところですが、  
下記を参照してぐっと我慢します。  
[JavaScriptのプロトタイプからオブジェクト指向を学ぶ](https://qiita.com/takeharu/items/809114f943208aaf55b3)

```js 
HomeView.prototype.template = Handlebars.compile($("#home-tpl").html());
EmployeeListView.prototype.template = 
            Handlebars.compile($("#employee-list-tpl").html());
```

5\. サービスが正常に初期化されたときにホームビューを表示するようにサービス初期化ロジックを変更します。Home Viewコンストラクタへの引数としてサービスを渡します。

```js 
service.initialize().done(function () {
    $('body').html(new HomeView(service).render().$el);
});
```

6\. アプリケーションをテストしてみましょう。
→エラー。
具体的にはHomeViewでthis.render()がundefinedになっている。

あ、HomeViewの変数宣言しているところの中にthis.renderとかを書くのね…。


ざっくりと処理の流れをまとめ。分かる人は飛ばしてください。  
フロントエンドでDOM操作くらいしかいじらないと、わからなくなりがちです。  

具体的な処理はapp.jsからスタートします。(それまでは関数の宣言などだけなので呼び出すときに考える)  

1\. HomeView.prototype.template → テンプレートをHomeViewのクラス自体が持つ共通変数に設定  
EmployeeListView.prototype.templateも同様。
注意書き:今更ではありますが、HomeViewには一つの変数しか書いてないように思えます。しかしそれはいわゆるコンストラクタ関数というもので、  
Javaなどで言うところのクラス宣言みたいなものです。
…と、下記の参考資料に書いてありました。  
[【JavaScript】コンストラクタ関数について(オブジェクトの生成)](https://qiita.com/To_BB/items/3da167e6b5f36d9ca608)  
newの有無でも意味が違ってくるのでくれぐれもお気をつけください…。(2時間くらい迷いました)

2\. EmployeeServiceのオブジェクトを生成します。(ここの処理は最初から変わっていません。)

3\. EmployeeServiceオブジェクトのinitializeメソッドを呼び出します。

4\. 完了次第、下記を実行します。

```js 
$('body').html(new HomeView(service).render().$el);
```

個々の処理を細かく分けると、
4-1\. 3.で使用していたEmployeeServiceオブジェクトを渡してHomeViewオブジェクトを作成
4-2\. 4-1.で作成したHomeViewオブジェクトのrenderメソッドを呼び出す
4-3\. renderメソッドの戻り値は4-2で作成したインスタンス自身です。つまり.$elはインスタンスに設定されたプロパティ  
を指します。  
参考:[JavaScriptの「this」は「4種類」？？](https://qiita.com/takeharu/items/9935ce476a17d6258e27)
4-4\. .$elはテンプレートhtmlのcontentクラスの要素以下に「employeeListViewの.$elプロパティ」を設定したものです。
このプロパティもfindByNameでsetEmployeesを呼び出した際にセットしたemployeesを元にテンプレートを使用したものなので細かい解説は割愛。


---

# 参考URL

[Module 9: Creating Views](http://ccoenraets.github.io/cordova-tutorial/creating-view-classes.html)

[Cordovaのチュートリアルをやってみる 第七回](https://qiita.com/tokky_se/items/ba37ffcbb4fc2c28369a)

[cordova&VSCodeで環境を構築するまでの右往左往メモ。](https://qiita.com/tokky_se/items/346429d234c91bece11d)

[JavaScriptのプロトタイプからオブジェクト指向を学ぶ](https://qiita.com/takeharu/items/809114f943208aaf55b3)

[【JavaScript】コンストラクタ関数について(オブジェクトの生成)](https://qiita.com/To_BB/items/3da167e6b5f36d9ca608)  

[JavaScriptの「this」は「4種類」？？](https://qiita.com/takeharu/items/9935ce476a17d6258e27)