「ソースコードには人格がでる」と思っているので、キレイに、かつ簡単に書きたい。
ということでAngularJSというMVC(MVW)フレームワークを使ってみた。
参考にしたTodoアプリは、ドットインストールの「AngularJSで作るToDoアプリ」を基にした。
詳細な説明については、ドットインストールを参照してほしい。
準備
私の場合、TypeScriptはVisualStudioで書いているので、NuGetから以下の型定義をインストールしておく。他のエディタを使っている場合は、GitHubなどからダウンロードしてください。
- angularjs.TypeScript.DefinitelyTyped
- jquery.TypeScript.DefinitelyTyped(※1)
※1:jQueryの型定義は、AngularJSの型定義をインストールしたら勝手にインストールされた。依存関係になっているらしい。
※2:AngularJSの本体はNuGetからインストールしてもよいが、私の環境ではうまく動かなかったので、ドットインストールのサンプル同様「http://code.angularjs.org/angular-1.0.1.min.js」を使用する。
View(HTML)
<!DOCTYPE html>
<html lang="ja" ng-app>
<head>
<meta charset="utf-8" />
<title>AngularJS + TypeScript</title>
<script src="http://code.angularjs.org/angular-1.0.1.min.js"></script>
<script src="app.js"></script>
<style>
.done-true{
color:gray;
text-decoration:line-through;
}
</style>
</head>
<body>
<h1>AngularJS + TypeScript</h1>
<div ng-controller="TaskCtrl">
<p>Finished Task: {{getDoneCount()}} / {{tasks.length}}</p>
<button ng-click="deleteDone()">Delete Finished</button>
<ul>
<li ng-repeat="task in tasks">
<input type="checkbox" ng-model="task.done" />
<span class="done-{{task.done}}">{{task.body}}</span>
<a ng-click="deleteTask($index)">[x]</a>
</li>
</ul>
<form ng-submit="addNew()">
<input type="text" ng-model="newTaskBody" />
<input type="submit" value="add" />
</form>
</div>
</body>
</html>
内容はほぼすべてドットインストールと同じ。
唯一違うのは、27行目の
ng-click=”deleteTask($index)”
の部分。これは他のメソッド同様に、TypeScript側で実装することにした。
Model + Controller (TypeScript)
タスク(内容と完了フラグ)をクラスに定義する。
class TaskItem {
body: string;
done: boolean;
}
次に、アプリ用スコープのインターフェースを作成する。
これを作ることで、TypeScriptでの強みである型チェックと自動補完が可能になる。
ちなみに継承している「ng.IScope」はAngularJSが持っているスコープ定義。
それを拡張するカタチで、ITaskScopeインターフェースを作成している。
interface ITaskScope extends ng.IScope {
// taskが入った配列
tasks: Array<taskitem>;
// 画面のテキストボックス
newTaskBody: string;
// 定義するメソッド
addNew: typeof TaskCtrl.prototype.addNew;
deleteTask: typeof TaskCtrl.prototype.deleteTask;
deleteDone: typeof TaskCtrl.prototype.deleteDone;
getDoneCount: typeof TaskCtrl.prototype.getDoneCount;
}
最後にコントローラクラスを作成する。
class TaskCtrl {
constructor(private $scope: ITaskScope) {
// 初期値
$scope.tasks = [
{ body: "do this 1", done: false },
{ body: "do this 2", done: false },
{ body: "do this 3", done: false },
{ body: "do this 4", done: false }
];
// $scopeにメソッドをひもづける
$scope.addNew = this.addNew.bind(this);
$scope.deleteTask = this.deleteTask.bind(this);
$scope.deleteDone = this.deleteDone.bind(this);
$scope.getDoneCount = this.getDoneCount.bind(this);
}
/**
* タスクの追加
*/
addNew(): void {
this.$scope.tasks.push({ body: this.$scope.newTaskBody, done: false });
this.$scope.newTaskBody = ''; // テキストボックスのクリア
}
/**
* タスクの削除
* @param index 削除する行番号
*/
deleteTask(index: number): void {
this.$scope.tasks.splice(index, 1);
}
/**
* 済タスクの一括削除
*/
deleteDone(): void {
var oldTask = this.$scope.tasks;
this.$scope.tasks = [];
oldTask.forEach(task => {
if (!task.done) this.$scope.tasks.push(task);
});
}
/**
* 完了済み件数の取得
* @return 完了済み件数
*/
getDoneCount(): number {
var count = 0;
this.$scope.tasks.forEach(task => {
count += task.done ? 1 : 0;
});
return count;
}
}
さいごに
今回作成したToDoアプリをGitHubにあげた。
Controllerなどは、実際に動かしながら見たほうが理解が早いと思うので、是非ご活用ください。
ただ、ふたつほど疑問に残るところがある。
ひとつは、AngularJSってMVCのフレームワークなので、Model・View・Controllerの3つが存在するはずなのに、サンプルではModelとControllerがまとまってしまっている(というかModelがない)
まるでWindowsフォームのView(Form1.csみたいなの)に全部書いているような感覚だ。
どうやってM・V・Cで分ければよいのか…。
もうひとつは、HTMLにいろいろ書き込まなければならないため、大きなWebアプリだとゴチャゴチャにならないのかなと。素のJavaScript勉強してるときは、HTML側にメソッド名書かない方がよいとかあったのに、このサンプルではバリバリ書いてある。
AngularJSについては、まだ全然わからないことばかりなので、今後も勉強していきたい。
上記2つの疑問も、分かり次第まとめてブログに投稿しようと思う。
以上
written by @bc_rikko
追記:2015/04/08 18:30
フレームワークを使わず、素のJavaScriptだけでMVCモデルのToDoアプリを作ってみた。
AngularJSを使った場合とくらべて、コード量が倍以上に膨れ上がっていた。
やはりMVCフレームワークは偉大だ…。
追記:2015/05/27 18:30
次はVue.jsで同じToDoアプリを作ってみた。
Vue.jsは学習コストが低いといわれているが、たしかにAngularJSと比べるとわかりやすい気がする。
0 件のコメント :
コメントを投稿