素のJavaScriptはとにかくコード量が多くなって面倒。
AngularJSは学習コストが高く、AngularJS2.0になると別モノになってしまう。
とにかく手軽にアプリが作れるフレームワークを、と探したところにMVVMフレームワークの「Vue.js」を見つけた。
ググるとなにかと「お手軽」というキーワードが目についたので、実際に使ってみた。
できあがったモノは、以下のサイトで触れる。
ToDoアプリ自体は、以下の2つのエントリとほとんど同じ。
準備
bower、tsd、NuGet、GitHubなどから以下のjsファイルと型定義ファイルをダウンロードする。
- vue
- vue.d.ts
View(HTML)
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Vue.js + TypeScript</title> <style> .done-true{ color: gray; text-decoration: line-through; } </style> </head> <body> <div id="todoapp"> <h1>Vue.js + TypeScript</h1> <p>Finished Task: {{getDoneCount}} / {{tasks.length}}</p> <button v-on="click: deleteDone">Delete Finished</button> <ul> <li v-repeat="task: tasks"> <input type="checkbox" v-model="task.done" /> <span class="done-{{task.done}}">{{$index}}:{{task.body}}</span> <a href="#" v-on="click: deleteTask($index)">[x]</a> </li> </ul> <form onsubmit="return false;" v-on="submit: addNew"> <input type="text" v-model="newTaskBody" /> <input type="submit" value="add" /> </form> </div> <script src="./bundle.js"></script> </body> </html>
見た目、AngularJSとほとんど変わらない。
「ng-hoge」が「v-hoge」に変わり、「ng-click」が「v-on="click hoge"」に変わっただけ。
ウチの環境では、webpackを使ってjsファイルをバンドル化しているので、scriptの読み込みが1行になっている。
実装したjsファイルとライブラリは分けたほうが良いと思うんだけど、どうなんだろう?
ViewModel (TypeScript)
ViewModelとは、Viewを描画するための状態の保持と、Viewから受け取った入力を適切なカタチに変換してModelに伝達する役割。
だけど、ToDoアプリ自体小さなプログラムなので今回はModel層はなし。
/// <reference path="./typings/vue/vue.d.ts" /> import Vue = require('vue'); interface ITask { body: string done: boolean } class TodoApp extends Vue{ // タスク一覧 tasks: ITask[]; // 新規タスク newTaskBody = ''; constructor() { // to defer compilation in Vue super(false); this._init({ el: '#todoapp', data: { tasks: this.tasks, newTaskBody: this.newTaskBody }, computed: { getDoneCount: this.getDoneCount }, created: () => { this.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 } ]; }, methods: { addNew: this.addNew, deleteTask: this.deleteTask, deleteDone: this.deleteDone } }); } /** * タスクの追加 */ addNew(): void{ var task = this.newTaskBody && this.newTaskBody.trim(); if (!task) { return; } this.tasks.push({ body: task, done: false }); this.newTaskBody = ''; } /** * タスクの削除 * @param index :削除する行番号 */ deleteTask(delIndex: number): void{ this.tasks.splice(delIndex, 1); } /** * 済タスクの一括削除 */ deleteDone(): void{ var oldTasks = this.tasks; this.tasks = []; oldTasks.forEach(task => { if (!task.done) this.tasks.push(task); }); } /** * 完了済み件数の取得 * @return 完了済み件数 */ getDoneCount(): number{ var count = 0; this.tasks.forEach(task => { count += task.done ? 1 : 0; }); return count; } } export var todoApp = new TodoApp();
1行目:型定義ファイル(vue.d.ts)の読み込み
3行目:前述の通り、Webpackを使っているので「import Vue = require(‘vue’)」なんてことをしている。
5行目:ひとつのタスクを表すinterface。それぞれのタスクに何かする機能を付けたいならclassにした方が良い。
10行目~87行目:ViewModelの実装
10行目:いろいろ実装するために、Vueを継承する。
12~14行目:ViewModelで保持するデータ(タスク一覧と新規タスク名)
18行目:Vueのコンストラクタにfalseを渡すと、コンパイルを遅延させられる。
20行目:見覚えのあるVueの定義は、this._initをオーバーライドするカタチで行う。
- el:対象となるHTML要素(Element)
- data:バインドする値
- computed:dataの値を利用した計算式のようなモノ
- created:初期化処理などに使う
- methods:イベントなどから呼び出す各種処理
48~88行目:computedやmethodsにバインドするメソッドの実装
91行目:最後にTodoAppクラスをインスタンス化してexportして終わり。インスタンス化だけでexportをしないと動かないので注意
さいごに
今回作成したToDoアプリをGitHubにあげた。
AngularJSと比較すると、$scopeとかよくわからないモノがない分、理解しやすかった。
慣れもあるのかもしれないが、直感的で書きやすい印象だった。
Componentを使った実装や、Modelの存在をないものとして扱ってきたが、今後機会があったらまたブログにまとめようと思う。
とにかく手軽にWebアプリケーションがつくりたい!というなら、Vue.jsは良い選択肢になると思う。
参考サイト
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿