形式 | 学習コスト | 参考文献 | View-Model連携 | 構成の定式化 | UIコンポーネント | |
knockout.js | MVVM (Model・View・ViewModel?) | 低 | 事例少(ただし本家のみで事足りる) | 双方向バインディング | なし | jQuery と連携可能 |
backbone.js | MVC2(Model・Collection・View・Router・History) | 中 | 事例豊富 | 手動 | 強力 | underscore.js/jQuery に依存 |
angular.js | MVW(Model・View・Whatever) | 大 | 事例少(本家の解説難解過ぎ) | 双方向バインディング | あり | angular-ui、ng-animate |
First name, Last name を変更して、フォーカスを移すと Full name が更新される
[~/KnockoutExam]$ tree . ├── README.md ├── js │ ├── knockoutEx1_init.js │ ├── knockoutEx1_model.js │ ├── knockoutEx1_vmodel.js │ ├── knockoutEx2_init.js │ ├── knockoutEx2_model.js │ ├── knockoutEx2_vmodel.js │ ├── knockoutEx3_init.js │ ├── knockoutEx3_model.js │ ├── knockoutEx3_vmodel.js │ └── lib │ ├── domReady.js │ ├── jquery-grid-4.7.1 │ │ ├── i18n │ │ │ ├── grid.locale-ar.js │ │ │ ├── grid.locale-bg.js │ │ │ ├ ... │ │ │ └── grid.locale-vi.js │ │ ├── jquery.jqGrid.min.js │ │ └── ui.jqgrid.css │ ├── jquery-ui-1.11.3 │ │ ├── external │ │ │ └── jquery │ │ │ └── jquery.js │ │ ├── images │ │ │ ├── ui-icons_444444_256x240.png │ │ │ ├── ui-icons_555555_256x240.png │ │ │ ├── ui-icons_777620_256x240.png │ │ │ ├── ui-icons_777777_256x240.png │ │ │ ├── ui-icons_cc0000_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ ├── index.html │ │ ├── jquery-ui.css │ │ ├── jquery-ui.js │ │ ├── jquery-ui.min.css │ │ ├── jquery-ui.min.js │ │ ├── jquery-ui.structure.css │ │ ├── jquery-ui.structure.min.css │ │ ├── jquery-ui.theme.css │ │ └── jquery-ui.theme.min.css │ ├── knockout-3.2.0.js │ ├── knockout-es5.js │ └── require.js ├── knockoutEx1_HelloKo.html ├── knockoutEx2_Ko+jQuery.html └── knockoutEx3_Ko+jqGrid.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Hello knockdown.js</title> <!-- require.js (http://requirejs.org/) を使って MVC のコードを分離する。 この HTML は、View層。Controller を require.js で読み込む。 Model と knockout.js などの依存ライブラリは、Controller から読み込む。 ※ require.js を使わずに knockout.js のみでアプリをつくる事もできる --> <script type="text/javascript" charset="UTF-8" src="js/lib/require.js" data-main="js/knockoutEx1_init.js"></script> </head> <body> <p>First name: <input data-bind="value: firstName" title="個人名を入力してください" /></p> <p>Last name : <input data-bind="value: lastName" title="姓を入力してください" /></p> <p>Full name : <strong data-bind="text: fullName"></strong></p> <button data-bind='click: registerClick, disable: isEnableRegister'>Search</button> </body> </html>
/* * アプリケーションのイニシャライザ. * ----------------------------------------------------------------------------- * HTML から呼び出されるモジュールは * require([mod1, mod2], function(if1, if2) { * // 処理 * } * と記述する。 * * 第一引数は、依存するライブラリ名。 * 第二引数は、画面の初期化を行う処理で、その引数は依存するライブラリ * のインタフェースオブジェクト。 * * 依存するライブラリは、AMD に準拠している必要がある。 * AMD に関しては knockoutEx1_model を参照してね */ require.config({ // Javascript の Base Url baseUrl: 'js/lib', // ライブラリのパスの別名を定義する paths: { 'app': '../', 'knockout': 'knockout-3.2.0' }, // AMDに対応してないモジュールを読み込む shim: { } }); require(['knockout', 'app/knockoutEx1_vmodel', 'app/knockoutEx1_model', 'domReady!'], function(ko, vmdl, mdl) { ko.applyBindings(new vmdl(new mdl())); } );
/* * アプリケーションの View Model. * * require から呼び出されるモジュールは * define([mod1, mod2], function(if1, if2) { * return function ifObj() { * var _name = ""; * this.getName = function() { return _name; }; * this.setName = function(name) { _name = name; }; * }; * } * と記述する。 * * これは、AMD ((Asynchronous Module Definition) に準拠している * モジュール定義。 * 第一引数は、依存するライブラリ名。 * 第二引数は、インタフェースオブジェクトを作成する処理で、引数は * 依存ライブラリのインタフェースオブジェクト。 */ define(['knockout'], function(ko) { return function appViewModel(mdl) { this.firstName = ko.observable(mdl.firstName); this.lastName = ko.observable(mdl.lastName); /** * フルネーム. */ this.fullName = ko.computed(function() { return this.firstName() + " " + this.lastName().toUpperCase(); }, this); /** * 登録ボタンクリック時の処理. */ this.registerClick = function() { // View Model を Model に書き戻す mdl.firstName = this.firstName(); mdl.lastName = this.lastName(); // 登録処理 (本当はサーバーアクセス) alert(JSON.stringify(mdl)); }; /** * 登録ボタンの有効化フラグ. */ this.isEnableRegister = ko.computed(function() { return '' === this.firstName() || '' === this.lastName(); }, this); }; });
/* * アプリケーションの Model. */ define(function() { return function appModel() { this.firstName = 'Bert'; this.lastName = 'Simpson'; }; });