実践 knockout   @hakurai
自己紹介• hakurai• Backlog開発チーム@ヌーラボ• 関ジャバ• hoge駆動• 奈良模型愛好会
1/10 新機能リリース!
knockoutをフル活用しました
KNOCKOUTについて• JavaScriptでMVVMを実現するフレームワーク • jQueryには依存していない • サポートブラウザ • IE   6+, Firefox 2+, Chrome, Safari, others
KNOCKOUTのコンセプト• 宣言型データバインディング• UIの自動更新• 依存性追跡• テンプレート
宣言型データバインディング• HTMLの要素とJavaScriptの値を結びつける • data-bind属性を要素に追加するだけ
data-bindの例 • div要素のテキストと                   vm.message の値をバインド<div data-bind="text: message"></div>                  vm = ...
hello world!を表示する例 <html xmlns="http://www.w3.org/1999/xhtml"><head>   <script type="text/javascript" src="../lib/knockout...
step1 data-bind属性を設定 <html xmlns="http://www.w3.org/1999/xhtml"><head>   <script type="text/javascript" src="../lib/knocko...
step2 ViewModelを定義 <html xmlns="http://www.w3.org/1999/xhtml"><head>   <script type="text/javascript" src="../lib/knockout...
step3 ViewとViewModelをバインド <html xmlns="http://www.w3.org/1999/xhtml"><head>   <script type="text/javascript" src="../lib/k...
6種類+ のbinding• visible   binding     • style   binding• text   binding        • attr   binding• html    binding       • cu...
visible binding• 要素の表示・非表示の切り替え• いわゆるdisplay:noneのon/offの切り替え • オブジェクトがtrueまたはnon-nullなら表示 • false,   0, null undefinedなら非表示...
text binding• オブジェクトをテキストとして要素に設定    <div data-bind="text: message"></div>
html binding• オブジェクトをinnerHTMLとして要素に設定 <div data-bind="html: message"></div>             vm = {                message: <s...
css binding• 要素のclassの追加・削除• オブジェクトがtrueならclassを追加• falseならclassを削除  <div data-bind="css:{selected: status}"></div>       ...
trueならclassを追加<div data-bind="css:{selected: status}"></div> vm = {    status: true };<div class= selected ></div>
falseならclassを削除<div data-bind="css:{selected: status}"></div> vm = {    status: false };<div></div>
複数指定もできます<div data-bind="css:{selected: status, warn: over}"></div>     vm = {        status: true,        over: true     ...
style binding• 要素のstyleを設定• css   bindingがあるので余り使わないかも   <div data-bind="style:{color: bg}"></div>                vm = {  ...
style bindingの注意点• スタイル名に-(ハイフン)は使えない• キャメルケースに書き換える• font-weight   → fontWeight• text-decoration   → textDecoration
attr binding• 要素の属性を設定• hrefとかsrcとか  <a data-bind="attr:{href: url}"></a>               vm = {                  url: http:...
custom binding• 好きな名前でbindingを自分で作れる• これまで紹介したbindingも同じ仕組でできている  <div data-bind="hoge: message"></div>             ko.bin...
UIの自動更新• UIとオブジェクトの状態を同期する• オブジェクトを同期するko.observable• 配列を同期するko.observableArray
UIの自動更新• ko.observableを使用していないプロパティは同期されない                同期されない      vm = {         name: aoshima ,         age: ko.obser...
最初のバインド• ko.applyBindingsの呼び出し時の値でバインドされる vm = {    name: aoshima ,    age: ko.observable(25) };                          ...
値の更新• nameはko.observableでラップされていない• 値が変わっても更新されない vm = {    name: aoshima ,    age: ko.observable(25) };                  ...
値の更新• ageはko.observableでラップされている• 値が変わると自動的に更新される vm = {    name: hakurai ,    age: ko.observable(25) };                  ...
依存関係追跡• オブジェクト同士に依存関係を持たせる• ko.computed • 別のko.observableの値が変更されると更新される
依存関係追跡• ko.computedに渡した関数内のko.observableの値が更新されるとko.computedの値も更新される     function vm(){        this.firstName =ko.observabl...
テンプレート • テンプレートを利用してオブジェクトを表示する <div data-bind="template: { name: person-template, data: buyer }"></div> <div data-bind="t...
<div data-bind="template: { name: person-template, data: buyer }">   <h3 data-bind="text: name">Franklin</h3>   <p>Credits...
Control flow• foreach   binding• if   binding• ifnot   binding• with    binding
foreach binding • 配列分要素を繰り返し追加する <ul data-bind= foreach: users >   <li data-bind= text: name ></li></ul>                  ...
foreach binding • この例の場合               li 要素が2つ分表示される <ul data-bind= foreach: users >   <li data-bind= text: name >hoge</l...
foreach bindingと自動更新 • UIを自動更新する場合はko.observableArrayを使う <ul data-bind= foreach: users >   <li data-bind= text: name ></li...
foreach bindingと自動更新 • pushで要素を追加すると                          li 要素も追加される <ul data-bind= foreach: users >   <li data-bind=...
if binding • オブジェクトがtrueの場合に要素を追加する <div data-bind= if: show >   <span>hello world</span></ul>                 vm = {     ...
ifnot binding • オブジェクトがtrueの場合に要素を追加しない <div data-bind= ifnot: notShow >   <span>hello world</span></ul>                  ...
with binding • バインディングコンテキストを変更する <span data-bind= text: title ></span><div data-bind= with: data >   <ul data-bind= forea...
with binding • vmオブジェクトのコンテキスト <span data-bind= text: title ></span><div data-bind= with: data >   <ul data-bind= foreach:...
with binding • vm.dataオブジェクトのコンテキスト <span data-bind= text: title ></span><div data-bind= with: data >   <ul data-bind= for...
with binding • 入れ子構造のオブジェクトにアクセスしやすくなる • 大きなViewModelを複数のオブジェクトに分割 <span data-bind= text: title ></span><div>   <ul data-b...
コンテキスト変数• $parent       • $parentContext• $parents      • $context• $root         • $element• $data• $index
親のコンテキストにアクセス• $parent       • $parentContext• $parents      • $context• $root         • $element• $data• $index
foreach中のオブジェクト• $parent                • $parentContext• $parents               • $context• $root                  • $ele...
現在の要素• $parent                    • $parentContext• $parents                   • $context• $root                      • $e...
working with form fields• click   binding     • value   binfing• event   binding     • hasfocus• submit    binding   • check...
click binding • クリック人のイベントハンドラを設定する <span data-bind= text: message ></span><button data-bind= click: onclick >click me</bu...
click binding• foreach中の要素の場合引数に対応するオブジェクト が渡される• 基本的にevent.preventDefaultされる • したくない場合は関数からtrueを返す
イベントバブリング  • data-bind中で<イベント名>Bubbleを指定する  • クリックイベントのバブリングを止める場合<button data-bind= click: onclick, clickBubble: false >c...
小ネタ
仮想要素サポート • コメントを使ってバインドを指定できる • 引数には更新後の値が渡される <ul>   <li>first</li>   <!-- ko foreach: items -->       <li data-bind= text...
ko.observable.subscribe• ko.observableの値が変更された時に呼び出す関数を設定できる• 引数には更新後の値が渡される     this.count = ko.observable(1);     this.c...
スロットル拡張• ko.observableの値が最後に変更されてから一定時間経った場合にUIを更新する  vm = {     count: ko.observable(1).extend({ throttle: 5000})  }  ko....
custom binding• jQueryを使ったDOM操作を隠蔽したり• 使いこなすと結構便利  ko.bindingHandlers.<バインド名> = {     init: function(element,valueAccessor...
ko.utils• ko.utils.unwrapObservable• ko.utils.arrayPushAll• など
サンプルコード• 公式サイトのチュートリアル • http://learn.knockoutjs.com/• https://github.com/hakurai/knockout-sample
• http://hakurai.github.com/javap.js/web/
まとめ• knockout便利!
Upcoming SlideShare
Loading in …5
×

実践Knockout

2,545 views

Published on

Published in: Technology
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,545
On SlideShare
0
From Embeds
0
Number of Embeds
53
Actions
Shares
0
Downloads
19
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide

実践Knockout

  1. 1. 実践 knockout @hakurai
  2. 2. 自己紹介• hakurai• Backlog開発チーム@ヌーラボ• 関ジャバ• hoge駆動• 奈良模型愛好会
  3. 3. 1/10 新機能リリース!
  4. 4. knockoutをフル活用しました
  5. 5. KNOCKOUTについて• JavaScriptでMVVMを実現するフレームワーク • jQueryには依存していない • サポートブラウザ • IE 6+, Firefox 2+, Chrome, Safari, others
  6. 6. KNOCKOUTのコンセプト• 宣言型データバインディング• UIの自動更新• 依存性追跡• テンプレート
  7. 7. 宣言型データバインディング• HTMLの要素とJavaScriptの値を結びつける • data-bind属性を要素に追加するだけ
  8. 8. data-bindの例 • div要素のテキストと vm.message の値をバインド<div data-bind="text: message"></div> vm = { message: hello world! }; ko.applyBindings(vm);
  9. 9. hello world!を表示する例 <html xmlns="http://www.w3.org/1999/xhtml"><head> <script type="text/javascript" src="../lib/knockout-2.1.0.js"></script></head><body><div data-bind="text: message"></div><script type="text/javascript" src="script.js"></script></body></html> (function(){ var vm = { message: hello world! }; ko.applyBindings(vm); }());
  10. 10. step1 data-bind属性を設定 <html xmlns="http://www.w3.org/1999/xhtml"><head> <script type="text/javascript" src="../lib/knockout-2.1.0.js"></script></head><body><div data-bind="text: message"></div><script type="text/javascript" src="script.js"></script></body></html> (function(){ var vm = { message: hello world! }; ko.applyBindings(vm); }());
  11. 11. step2 ViewModelを定義 <html xmlns="http://www.w3.org/1999/xhtml"><head> <script type="text/javascript" src="../lib/knockout-2.1.0.js"></script></head><body><div data-bind="text: message"></div><script type="text/javascript" src="script.js"></script></body></html> (function(){ var vm = { message: hello world! }; ko.applyBindings(vm); }());
  12. 12. step3 ViewとViewModelをバインド <html xmlns="http://www.w3.org/1999/xhtml"><head> <script type="text/javascript" src="../lib/knockout-2.1.0.js"></script></head><body><div data-bind="text: message"></div><script type="text/javascript" src="script.js"></script></body></html> (function(){ var vm = { message: hello world! }; ko.applyBindings(vm); }());
  13. 13. 6種類+ のbinding• visible binding • style binding• text binding • attr binding• html binding • custom binding• css binding
  14. 14. visible binding• 要素の表示・非表示の切り替え• いわゆるdisplay:noneのon/offの切り替え • オブジェクトがtrueまたはnon-nullなら表示 • false, 0, null undefinedなら非表示 <div data-bind="visible: showMsg">hello world!</div>
  15. 15. text binding• オブジェクトをテキストとして要素に設定 <div data-bind="text: message"></div>
  16. 16. html binding• オブジェクトをinnerHTMLとして要素に設定 <div data-bind="html: message"></div> vm = { message: <strong>hello world!</strong> };
  17. 17. css binding• 要素のclassの追加・削除• オブジェクトがtrueならclassを追加• falseならclassを削除 <div data-bind="css:{selected: status}"></div> vm = { status: true };
  18. 18. trueならclassを追加<div data-bind="css:{selected: status}"></div> vm = { status: true };<div class= selected ></div>
  19. 19. falseならclassを削除<div data-bind="css:{selected: status}"></div> vm = { status: false };<div></div>
  20. 20. 複数指定もできます<div data-bind="css:{selected: status, warn: over}"></div> vm = { status: true, over: true }; <div class= selected over ></div>
  21. 21. style binding• 要素のstyleを設定• css bindingがあるので余り使わないかも <div data-bind="style:{color: bg}"></div> vm = { bg: red };
  22. 22. style bindingの注意点• スタイル名に-(ハイフン)は使えない• キャメルケースに書き換える• font-weight → fontWeight• text-decoration → textDecoration
  23. 23. attr binding• 要素の属性を設定• hrefとかsrcとか <a data-bind="attr:{href: url}"></a> vm = { url: http://www.backlog.jp/ };
  24. 24. custom binding• 好きな名前でbindingを自分で作れる• これまで紹介したbindingも同じ仕組でできている <div data-bind="hoge: message"></div> ko.bindingHandlers.hoge = { init: function(){}, update: function(){} };
  25. 25. UIの自動更新• UIとオブジェクトの状態を同期する• オブジェクトを同期するko.observable• 配列を同期するko.observableArray
  26. 26. UIの自動更新• ko.observableを使用していないプロパティは同期されない 同期されない vm = { name: aoshima , age: ko.observable(25) }; 同期される
  27. 27. 最初のバインド• ko.applyBindingsの呼び出し時の値でバインドされる vm = { name: aoshima , age: ko.observable(25) }; aoshima 25 ko.applyBindings(vm); name = hasegawa ; age(26);
  28. 28. 値の更新• nameはko.observableでラップされていない• 値が変わっても更新されない vm = { name: aoshima , age: ko.observable(25) }; aoshima 25 ko.applyBindings(vm); name = hasegawa ; age(26);
  29. 29. 値の更新• ageはko.observableでラップされている• 値が変わると自動的に更新される vm = { name: hakurai , age: ko.observable(25) }; aoshima 26 ko.applyBindings(vm); name = hasegawa ; age(26);
  30. 30. 依存関係追跡• オブジェクト同士に依存関係を持たせる• ko.computed • 別のko.observableの値が変更されると更新される
  31. 31. 依存関係追跡• ko.computedに渡した関数内のko.observableの値が更新されるとko.computedの値も更新される function vm(){ this.firstName =ko.observable(Bob); this.lastName =ko.observable(Smith); this.fullName = ko.computed(function () { return this.firstName() + " " + this.lastName(); }, this); }
  32. 32. テンプレート • テンプレートを利用してオブジェクトを表示する <div data-bind="template: { name: person-template, data: buyer }"></div> <div data-bind="template: { name: person-template, data: seller }"></div><script type="text/html" id="person-template"> <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p></script> vm = { buyer: { name: Franklin, credits: 250 }, seller: { name: Mario, credits: 5800 } }
  33. 33. <div data-bind="template: { name: person-template, data: buyer }"> <h3 data-bind="text: name">Franklin</h3> <p>Credits: <span data-bind="text: credits">250</span></p></div> <div data-bind="template: { name: person-template, data: seller }"> <h3 data-bind="text: name">Mario</h3> <p>Credits: <span data-bind="text: credits">5800</span></p></div> テンプレートが展開された vm = { buyer: { name: Franklin, credits: 250 }, seller: { name: Mario, credits: 5800 } }
  34. 34. Control flow• foreach binding• if binding• ifnot binding• with binding
  35. 35. foreach binding • 配列分要素を繰り返し追加する <ul data-bind= foreach: users > <li data-bind= text: name ></li></ul> vm = { users: [{name: hoge }, {name: fuga }] }
  36. 36. foreach binding • この例の場合 li 要素が2つ分表示される <ul data-bind= foreach: users > <li data-bind= text: name >hoge</li> <li data-bind= text: name >fuga</li></ul> users配列分繰り返し vm = { users: [{name: hoge }, {name: fuga }] }
  37. 37. foreach bindingと自動更新 • UIを自動更新する場合はko.observableArrayを使う <ul data-bind= foreach: users > <li data-bind= text: name ></li></ul> vm = { users: ko.observableArray( [{name: hoge }, {name: fuga }] ) };
  38. 38. foreach bindingと自動更新 • pushで要素を追加すると li 要素も追加される <ul data-bind= foreach: users > <li data-bind= text: name >hoge</li> <li data-bind= text: name >fuga</li> <li data-bind= text: name >piyo</li></ul> vm.users.push({name: piyo });
  39. 39. if binding • オブジェクトがtrueの場合に要素を追加する <div data-bind= if: show > <span>hello world</span></ul> vm = { show: ko.observable(false); }
  40. 40. ifnot binding • オブジェクトがtrueの場合に要素を追加しない <div data-bind= ifnot: notShow > <span>hello world</span></ul> vm = { notShow: ko.observable(false); }
  41. 41. with binding • バインディングコンテキストを変更する <span data-bind= text: title ></span><div data-bind= with: data > <ul data-bind= foreach: users > <li data-bind= text: name ></li> </ul> vm = {</div> title: hello data: { users: [{name: hoge }, {name: fuga }] } }
  42. 42. with binding • vmオブジェクトのコンテキスト <span data-bind= text: title ></span><div data-bind= with: data > <ul data-bind= foreach: users > <li data-bind= text: name ></li> </ul> vm = {</div> title: hello data: { users: [{name: hoge }, {name: fuga }] } }
  43. 43. with binding • vm.dataオブジェクトのコンテキスト <span data-bind= text: title ></span><div data-bind= with: data > <ul data-bind= foreach: users > <li data-bind= text: name ></li> </ul> vm = {</div> title: hello data: { users: [{name: hoge }, {name: fuga }] } }
  44. 44. with binding • 入れ子構造のオブジェクトにアクセスしやすくなる • 大きなViewModelを複数のオブジェクトに分割 <span data-bind= text: title ></span><div> <ul data-bind= foreach: data.users > <li data-bind= text: name ></li> </ul></div>
  45. 45. コンテキスト変数• $parent • $parentContext• $parents • $context• $root • $element• $data• $index
  46. 46. 親のコンテキストにアクセス• $parent • $parentContext• $parents • $context• $root • $element• $data• $index
  47. 47. foreach中のオブジェクト• $parent • $parentContext• $parents • $context• $root • $element• $data• $index 配列中のインデックス
  48. 48. 現在の要素• $parent • $parentContext• $parents • $context• $root • $element <div id= item1 data-bind= text: $element.id ></div>• $data item1• $index
  49. 49. working with form fields• click binding • value binfing• event binding • hasfocus• submit binding • checked binding• enable binding • options binding• disable binding • selectedOptions binding • uniqueName binding
  50. 50. click binding • クリック人のイベントハンドラを設定する <span data-bind= text: message ></span><button data-bind= click: onclick >click me</button> vm = { message: ko.observable(), onclick: function(data, event){ this.message( hello world! ); } }
  51. 51. click binding• foreach中の要素の場合引数に対応するオブジェクト が渡される• 基本的にevent.preventDefaultされる • したくない場合は関数からtrueを返す
  52. 52. イベントバブリング • data-bind中で<イベント名>Bubbleを指定する • クリックイベントのバブリングを止める場合<button data-bind= click: onclick, clickBubble: false >click me</button>
  53. 53. 小ネタ
  54. 54. 仮想要素サポート • コメントを使ってバインドを指定できる • 引数には更新後の値が渡される <ul> <li>first</li> <!-- ko foreach: items --> <li data-bind= text: $data ></li> <!-- /ko --></ul>
  55. 55. ko.observable.subscribe• ko.observableの値が変更された時に呼び出す関数を設定できる• 引数には更新後の値が渡される this.count = ko.observable(1); this.count.subscribe(function(newValue){ alert(newValue); });
  56. 56. スロットル拡張• ko.observableの値が最後に変更されてから一定時間経った場合にUIを更新する vm = { count: ko.observable(1).extend({ throttle: 5000}) } ko.applyBindings(vm); vm.count(2); 5 秒後に 2 に更新される
  57. 57. custom binding• jQueryを使ったDOM操作を隠蔽したり• 使いこなすと結構便利 ko.bindingHandlers.<バインド名> = { init: function(element,valueAccessor){ // applyBinding 時に一度だけ呼ばれる // 主に element に対してイベントハンドラを追加したりする }, update: function(element, valueAccessor){ // バインドしたko.observable()が変更されると呼ばれる // element を更新したりする } };
  58. 58. ko.utils• ko.utils.unwrapObservable• ko.utils.arrayPushAll• など
  59. 59. サンプルコード• 公式サイトのチュートリアル • http://learn.knockoutjs.com/• https://github.com/hakurai/knockout-sample
  60. 60. • http://hakurai.github.com/javap.js/web/
  61. 61. まとめ• knockout便利!

×