Knockout.js を利用したインタラクティブ web アプリケーション開発

4,465 views

Published on

2014 年 03 月 22 日に開催された MVP Community Camp 2014 名古屋会場で発表させていただいたセッション資料です。

Published in: Technology

Knockout.js を利用したインタラクティブ web アプリケーション開発

  1. 1. Knockout.js を利用した インタラクティブ Web アプリケーション開発 池原 大然 デベロッパー エバンジェリスト インフラジスティックス・ジャパン株式会社 dikehara@Infragistics.com
  2. 2. アジェンダ セッションの動機など Knockout.js の特長 カスタム バインディングを利用した拡張 まとめ
  3. 3. セッションの動機
  4. 4. 自己紹介 池原 大然(いけはら だいぜん) インフラジスティックス・ジャパン株式会社 デベロッパー エバンジェリスト Microsoft MVP for Development Platforms Client App Dev 2010/04 – 2014/03 @Neri78 Blog
  5. 5. 開発ツール製品
  6. 6. そもそものセッションの動機 • もともと XAML が好きだった –いちおう XAML 系の MVP • 仕事柄 jQuery 対応コンポーネントについても 理解を深めないといけない • JavaScript でバインディングときいて • “コントロール” に関係のあるセッションをしたい
  7. 7. ゴール 1. Knockout.js の概要をおさえる 2. カスタムバインディングの概要をおさえる
  8. 8. Knockout.js の 特長
  9. 9. すべてはここから http://knockoutjs.com
  10. 10. ライブラリの参照 <head> <script type='text/javascript' src='knockout-3.1.0.js'></script> </head> js ファイルの参照 <head> <!-- 次のうちいずれか --> <!-- Microsoft CDN knockout.js version 3.0.0 --> <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js" ></script> <!– CDNJS knockout.js version 3.1.0 --> <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script> </head> CDN の利用
  11. 11. キーコンセプト 宣言型 バインディング 自動 UI 更新 依存関係の トラッキング テンプレート 機能
  12. 12. Demo 基本的な機能の確認
  13. 13. 宣言型バインディング var person = { lastName: ‘池原’, firstName: ‘大然’, photo: ‘/Images/Daizen2011.png’ }; HTML 姓: <input id="lastName" data-bind="value: lastName" /> <br /> 名: <input id="firstName" data-bind="value: firstName" /> <br /> <img style="height:300px; width:400px" data-bind="attr: { src: photo }" /> <br /> <label id="fullName" data-bind="text: '氏名: ' + lastName + firstName"></label> html にデータの値を宣言できる この例では value, attr, text バインディングを使用 バインディングを実行 ko.applyBindings(person);
  14. 14. 標準で提供されているバインディング テキストおよび外観 のコントロール •text •html •css •style •attr コントロール フロー •foeach •if •ifnot •with 入力フィールド関連 •click •event •submit •enable •disable •value •hasFocus •checked •options •selectedOptions •uniqueName テンプレート •template
  15. 15. 自動 UI 更新 var person = { lastName: ko.observable(‘池原’), firstName: ko.observable(‘大然’), photo: ko.observable(‘/Images/Daizen2011.png’) }; HTML 双方向での値のやり取り が可能 データ更新 → UI 更新 UI 更新 → データ更新
  16. 16. Observable / ObservableArray • ko.observable – シングル プロパティ用 • 宣言: propertyName = ko.observable(初期値) • Read: propertyName() • Write: propertyName(新しい値) • ko.observableArray – 配列用 • 宣言: arrayName = ko.observableArray(配列) • Read: arrayName()[0] • Add/Remove: arrayName.push (), arrayName.remove()
  17. 17. 依存関係のトラッキング var viewModel = { lastName: ko.observable(‘池原’), firstName: ko.observable(‘大然’), photo: ko.observable(‘/Images/Daizen2011.png’) }; viewModel.fullName = ko.computed(function () { return viewModel.lastName() + ' ' + viewModel.firstName(); }, viewModel); fullName は lastName と firstName に依存しており、 どちらかが変更されると自身の値も更新される。
  18. 18. テンプレート機能 • 指定した DOM要素を追加、特に繰り返しの処理などに有用 </head> <!-- テンプレート --> <script type="text/html" id="person-template"> <tr> <td><span data-bind="text: lastName"></span></td> <td><span data-bind="text: firstName"></span></td> <td><img style="width: 200px; height:100px" data-bind="attr: { src: photo}" /></td> </tr> </script> </head> <body> <table> <thead> <tr> <th>氏</th> <th>名</th> <th>画像</th> </tr> </thead> <tbody data-bind="template: { name: 'person-template', foreach: people}" > </tbody> </table> </body>
  19. 19. さらに詳しく… http://shiba-yan.hatenablog.jp/category/Knockout.js 丸投げ
  20. 20. カスタム バインディング の利用
  21. 21. 標準で提供されているバインディング テキストおよび外観 のコントロール •text •html •css •style •attr フローの コントロール •foeach •if •ifnot •with 入力フィールド関連 •click •event •submit •enable •disable •value •hasFocus •checked •options •selectedOptions •uniqueName テンプレート •template HTML 要素に対しては非常に有用
  22. 22. 問題:コンポーネントと組み合わせる場合 • jQuery UI ProgressBar コントロールの値とラベルの 値の同期 標準のバインディングでは難しい…
  23. 23. カスタム バインディング • 独自のバインディングを構築することで コントロールに手を入れずに Knockout.js に 対応させることが可能 • 下記のようなバインディング方法を想定 <div id="progress" style="width:300px" data-bind="jQUIprogressBar: progressValue"></div>
  24. 24. 構文 ko.bindingHandlers.jQUIprogressBar = { init: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // バインディングの初期化処理 // progressBar は 1 方向(データ → UI ) で完結するのでシンプル }, update: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // バインディングの初期化時および値の変更時に行う処理 } };
  25. 25. パラメーター • element – バインディングの対象となる DOM 要素 • valueAccessor – バインディングに使用される値を呼び出すことができる JavaScript 関数。 ko.unwrap を利用することで observable、非 observable の値を取得できる • allBindings – バインディング対象にバインドされているすべての値 • allBindings.get(名前)で値の取得(存在しない場合は undefined)、allBindings.has(名 前) で存在の確認 • viewModel – 3.0 から廃止、代替手段として bindingContext.$data または bindingContext.$rawData を 利用する • bindingContext – このバインディングにおいてアクセスできる bindingContext
  26. 26. シンプルな拡張
  27. 27. 初期化の例 ko.bindingHandlers.jQUIprogressBar = { init: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // progressBar は 1 方向(データ → UI ) で完結するのでシンプル // プログレスバー var pbar = element; // バインドされた値 var progressValue = ko.unwrap(valueAccessor()); // ここでプログレスバーを初期化、View 側のコードでは呼び出さない $(pbar).progressbar({ value: progressValue}); }, };
  28. 28. 値の変更時の例 ko.bindingHandlers.jQUIprogressBar = { update: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // プログレスバー var pbar = element; // 更新された値 var progressValue = ko.unwrap(valueAccessor()); // 更新を反映 $(pbar).progressbar("option", "value", progressValue); } };
  29. 29. 考えられるシナリオ(1) • 複数の値を渡したい場合は? – progressBar に value と max を渡したい <div id="progress" style="width:300px" data-bind="jQUIprogressBar2: { value: progressValue, max: maxValue}"> </div> propgressbar の初期化値と 同じ形式にしておく
  30. 30. 考えられるシナリオ(2) • バインディングが 2 方向に渡る場合は? – 例: jQuery UI Slider の value は 2 方向で利用される可能性がある – Slider の値変更イベントを extension 側で制御 <div id="slider" style="width:300px" data-bind="jQuerySliderValue: progressValue"></div>
  31. 31. 複雑な拡張
  32. 32. 初期化の例 ko.bindingHandlers.jQUIprogressBar2 = { init: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // プログレスバー var pbar = element; // バインドされた値 var options = ko.unwrap(valueAccessor()); // 値の取得を試行 var max = ko.unwrap(options.max); if (max !== undefined) { options.max = max; } // 値の取得を試行 var value = ko.unwrap(options.value); if (value !== undefined) { options.value = value; } // ここでプログレスバーを option 付きで初期化 例: { value: 10, max: 100} というような形式になる $(pbar).progressbar(options); }, };
  33. 33. 値の変更時の例 ko.bindingHandlers.jQUIprogressBar2 = { update: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { //// プログレスバー var pbar = element; // バインドされた値 var options = ko.unwrap(valueAccessor()); // 値の取得を試行 var max = ko.unwrap(options.max); if (max !== undefined) { $(pbar).progressbar("option", "max", max); } // 値の取得を試行 var value = ko.unwrap(options.value); if (value !== undefined) { $(pbar).progressbar("option", "value", value); } } };
  34. 34. 2 方向のサポートの実装例 ko.bindingHandlers.jQuerySliderValue = { init: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { // Slider var slider = element; // バインドされた値 var value = ko.unwrap(valueAccessor()); if (value !== undefined) { // ここでプログレスバーを初期化 $(slider).slider({ value: value, change: function (event, el) { if (value != el.value) { // 値をバインディングソースに書き戻す valueAccessor()(parseInt(el.value)); } } }); } }, update: function ( element, valueAccessor, allBindings, viewModel, bindingContext) { var el = $(element); var value = ko.utils.unwrapObservable(valueAccessor()()); if (value !== el.val()) { el.slider("value", value); } } };
  35. 35. http://jp.igniteui.com
  36. 36. Ignite UI コンポーネント jQuery jQuery UI jQuery Mobile jQuery Mobile ベース コントロール jQuery ベース データ コンポーネント jQuery UI ベース コントロール
  37. 37. 収録コンポーネント:一覧 • データ グリッド – Grid – Hierarchical Grid • OLAP ピボット – Pivot Data Selector – Pivot View – Pivot Grid • データ ビジュアリゼーション – Data Chart – Bullet Graph – Pie Chart – Linear Gauge – Doughnut Chart – Map – Funnel Chart – Barcode – Radial Gauge – Zoombar – Sparkline • レイアウト – Layout Manager – Tile Manager – Splitter • エディター – Combo Box – Editors – Date Picker – HTML Editor • フレームワーク – Infragistics Loader – Data Source – Templating Engine – Infragistics Excel* – Infragistics Word* – Infragistics Document* • 操作 – Tree – Popover – Dialog Window – Rating – File Upload – Video Player • モバイル – List View – Rating – Button – Check Box – Check Box Group – Collapsible – Collapsible Set – RadioButton Group – SelectMenu – Slider – Toggle Switch – TextBox – Page – PageContent – PageFooter – PageHeader – Popup – Link – NavBar *ASP.NET 用サーバー側コンポーネント • jQuery ベース • jQuery UI ベース • jQuery Mobile ベース 併せて ASP.NET MVC 用ラッパークラスも提供
  38. 38. Knockout.js 対応 • 下記コントロールで一部のプロパティに対して Knockout.js 対応済み – Grid – Chart – Combo – Editor – Tree
  39. 39. http://jp.igniteui.com 少しだけ紹介 – Knockout.js 対応を中心に
  40. 40. まとめ
  41. 41. まとめ • Knockout.js を利用することで、画面実装者は 楽をできる可能性が! –標準 html タグ ベースの UI では適用範囲が広い • ただし、共通部品部隊や標準化部隊は大変かもしれない –ベンダーが対応できない or しない時など
  42. 42. リソース 公式サイト http://knockoutjs.com 非公式日本語ドキュメント http://kojs.sukobuto.com/ しばやん雑記 – かなりの情報が公開されています http://shiba-yan.hatenablog.jp/category/Knockout.js jQuery, XAML 対応製品を中心に紹介しているブログ http://blogs.jp.infragistics.com/blogs/dikehara/
  43. 43. http://jp.igniteui.com こちらもよろしく!

×