JavaScriptMVC を使ってプロジェクトを作成します。 この記事の続きです。
- JavaScriptMVC - 概要 (2011年8月25日)
ツールの準備
github から ZIP パッケージをダウンロードして適当なディレクトリに展開します。 この記事を書いている時点での最新版は javascriptmvc-3.1.0.zip です。
中身を見ておくと次のようになります。
$ ls MIT-LICENSE.txt documentjs/ jquery/ js.bat* changelog.txt funcunit/ js* steal/ $ ls steal/ jquery/ funcunit/ documentjs/ documentjs/: README distance.js doc.bat jmvcdoc/ scripts/ showdown.js test/ update build.js doc* documentjs.js json.js searchdata.js tags/ types/ funcunit/: README drivers/ generate_docs.html qunit/ summary.ejs autosuggest/ envjs* index.html qunit.html syn/ build.js envjs.bat* java/ resources/ template.html dependencies.json funcunit.html loader.js scripts/ test/ docs.html funcunit.js pages/ settings.js update jquery/: README buildAll.js controller/ download/ generate/ lang/ qunit.html tie/ view/ build.js class/ dom/ event/ jquery.js model/ test/ update steal/: README coffee/ getjs parse/ steal.production.js build/ dev/ js* patchfile test/ buildjs end.js js.bat pluginifyjs update clean/ generate/ less/ rhino/ cleanjs get/ make.js steal.js
単純な JavaScript だけでなく、 QUnit, CoffeeScript, LESS なども同梱されていることが分かります。 また、 steal の中には Rhino もありますね。 ちょっと JavaScript を動かしてみるには良い環境だと思います。
アプリケーションの作成
js コマンドが Rhino へのラッパーになっており、 steal を使ってアプリケーションを管理します。
"cookbook" アプリケーションを作成してみます。
$ ./js steal/generate/app cookbook cookbook/cookbook.css cookbook/cookbook.html cookbook/cookbook.js cookbook/docs cookbook/resources cookbook/resources/example.coffee cookbook/resources/example.js cookbook/resources/example.less cookbook/scripts cookbook/scripts/build.html cookbook/scripts/build.js cookbook/scripts/clean.js cookbook/test
cookbook/cookbook.html を開いてエラーが出ないことを確認します。 StealJS がパス解決に失敗している部分があると後で大変なので、 FireBug や開発者コンソールなどで確認しておきましょう。
ファイルシステム上のファイルを直接開くと Cross origin リクエストのエラーになるブラウザもあります。 HTTP サーバを起動しておくと便利です。 js コマンドを実行したディレクトリで python -m SimpleHTTPServer を実行すると、 8000番ポートからアクセスできます。 Mac OS X の場合は Web 共有で Apache が起動しますので、 ~/Sites 以下に配置すれば HTTP 経由でアクセスできます。
次に、データモデルを定義します。 scaffold を使うことで、MVC で言うモデルとコントローラーを生成してくれます。
$ mkdir cookbook/models $ ./js jquery/generate/scaffold Cookbook.Models.Recipe cookbook/controllers cookbook/controllers/recipe_controller.js cookbook/fixtures cookbook/fixtures/recipes.json.get cookbook/models cookbook/models/recipe.js cookbook/test cookbook/test/funcunit cookbook/test/funcunit/recipe_controller_test.js cookbook/test/qunit cookbook/test/qunit/recipe_test.js cookbook/views cookbook/views/recipe cookbook/views/recipe/edit.ejs cookbook/views/recipe/init.ejs cookbook/views/recipe/list.ejs cookbook/views/recipe/show.ejs
ここでサクッとモデルとコントローラーを使えると良いのですが、 JavaScriptMVC 2 系まであった .models() と .controllers() インターフェイスは廃止されました。
そこで、 cookbook.js を以下のように編集します。 コードジェネレーターで生成されたファイルは LESS と CoffeeScript を読み込むようになっていますが、 この部分は一旦コメントアウトか削除しておきます。
steal .plugins('jquery/model', 'jquery/view/ejs') .then('models/recipe') .then(function() { $('#content').append($.View('//cookbook/views/recipe/init.ejs', {recipes: []})); }) ;
まず、モデルとビューのプラグインを読み込みます。 ビューには EJS (EmbeddedJS), Micro, jQuery.Tmpl, JAML がありますが、 コードジェネレーターのデフォルトが EJS なので、これをそのまま使います。
次に、 cookbook/models/recipe.js で定義されるモデルクラス (Cookbook.Models.Recipe) を読み込みます。 .then() で指定する場合には .js の拡張子を省略します。 モデルクラスをここで読み込むのは、後から読み込むテンプレートファイルで参照しているためです。
最後の .then() にはコールバック関数を指定します。 最初に生成した cookbook.html には ID が "content" の <div> タグがありますので、 そこに HTML 要素を追加します。 $.View の最初の引数にテンプレートファイルへのパスを指定し、 二つ目の引数でパラメータを渡します。 パス表記はスラッシュふたつで始めています。 Web サーバ上での配置を考えるのが面倒な場合にはこのように書いておきます。
HTML ファイル (cookbook.html) をブラウザで開いてみると、 レシピの一覧と新しいレシピを登録するフォームのひな形が表示されています。
これでアプリケーションを実装する準備ができました。
データの表示
一覧表示
サンプルデータを表示させます。 cookbook/fixtures/recipes.json.get の中身を cookbook.js にコピーし、 テンプレートに渡します。 先ほどのコールバック関数を次のように変更します。
.then(function() { var recipes = [ {"name": "Take Out Trash", "description": "To the curb!", "id": 5} ]; $('#content').append($.View('//cookbook/views/recipe/init.ejs', {recipes: recipes})); })
続いてテンプレートを修正します。 init.ejs は list.ejs を呼び出し、その中で要素をループさせて show.ejs を呼び出します。 自動生成された show.ejs ではエラーが発生しますので、以下のように書き換えます。
<%for(var attribute in this){%> <%if(attribute == 'id') continue;%> <td class='<%= attribute%>' style="border:solid 1px gray; padding: 5px;"> <%=this[attribute]%> </td> <%}%> <td> <a href='javascript://' class='edit'>edit</a> <a href='javascript://' class='destroy'>destroy</a> </td>
cookbook.html をリロードすると次のようになります。 サンプルデータ (recipes 変数) を増やすと、一覧表示のデータに反映されます。
フォーム作成
モデルに属性を追加します。 Cookbook.Models.Recipe にはスタティックメソッドとプロトタイプメソッドが定義されています。 /* @Static */ のどこかに attributes を追加します。 辞書のキーはデータのキーと合わます。バリューは適当に当てています。
attributes: { 'id': 'integer', 'name': 'string', 'description': 'text' }
ブラウザで確認してみると、"New recipe" の部分にふたつのテキストボックスが追加され、 "recipes" の一覧表にタイトルが追加されていますね。
スタイルシートの分離
先ほどはテンプレートファイルの中に style 属性を記述しました。 これを外部ファイル化します。 方法はふたつあり、通常の CSS で管理する方法と、LESS を使う方法です。
終わりに
JavaScriptMVC を使ってアプリケーションのひな形と、簡単なデータを表示しました。 表示方法は複数のテンプレートシステムから選択でき、デザインには CSS だけでなく LESS も使えます。
新しいテンプレートや LESS、それから CoffeeScript は、 記法に慣れてしまえばサクサクと実装できるでしょうが、 不慣れな場合には覚えることが多くなってしまうことも事実です。 とはいえ、愚直に JavaScript や CSS を書いてブラウザごとの違いに泣かされるよりは、 最近流行り始めているかもしれない手法を取り入れた方が手っ取り早いと思います。
次は、QUnit と funcunit を使ってテストを動かしてみます。
0 件のコメント:
コメントを投稿