SlideShare a Scribd company logo
1 of 61
Download to read offline
実践 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 = {
                     message: hello world!
                  };


                  ko.applyBindings(vm);
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);
  }());
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);
  }());
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);
  }());
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);
  }());
6種類+ のbinding
• visible   binding     • style   binding

• text   binding        • attr   binding

• html    binding       • custom    binding

• css    binding
visible binding
• 要素の表示・非表示の切り替え


• いわゆるdisplay:noneのon/offの切り替え


 • オブジェクトがtrueまたはnon-nullなら表示


 • false,   0, null undefinedなら非表示

            <div data-bind="visible: showMsg">hello world!</div>
text binding
• オブジェクトをテキストとして要素に設定




    <div data-bind="text: message"></div>
html binding
• オブジェクトをinnerHTMLとして要素に設定




 <div data-bind="html: message"></div>




             vm = {
                message: <strong>hello world!</strong>
             };
css binding
• 要素のclassの追加・削除


• オブジェクトがtrueならclassを追加


• falseならclassを削除
  <div data-bind="css:{selected: status}"></div>




              vm = {
                 status: true
              };
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
     };




    <div class= selected over ></div>
style binding
• 要素のstyleを設定


• css   bindingがあるので余り使わないかも


   <div data-bind="style:{color: bg}"></div>




                vm = {
                   bg: red
                };
style bindingの注意点
• スタイル名に-(ハイフン)は使えない


• キャメルケースに書き換える


• font-weight   → fontWeight

• text-decoration   → textDecoration
attr binding
• 要素の属性を設定


• hrefとかsrcとか



  <a data-bind="attr:{href: url}"></a>




               vm = {
                  url: http://www.backlog.jp/
               };
custom binding
• 好きな名前でbindingを自分で作れる


• これまで紹介したbindingも同じ仕組でできている



  <div data-bind="hoge: message"></div>




             ko.bindingHandlers.hoge = {
                init: function(){},
                update: function(){}
             };
UIの自動更新
• UIとオブジェクトの状態を同期する


• オブジェクトを同期するko.observable


• 配列を同期するko.observableArray
UIの自動更新
• ko.observableを使用していないプロパティは同期さ
れない
                同期されない
      vm = {
         name: aoshima ,
         age: ko.observable(25)
      };
                   同期される
最初のバインド
• ko.applyBindingsの呼び出し時の値でバインドされ
る

 vm = {
    name: aoshima ,
    age: ko.observable(25)
 };                          aoshima
                               25
 ko.applyBindings(vm);


 name = hasegawa ;
 age(26);
値の更新
• nameはko.observableでラップされていない


• 値が変わっても更新されない

 vm = {
    name: aoshima ,
    age: ko.observable(25)
 };                                 aoshima
                                      25
 ko.applyBindings(vm);


 name = hasegawa ;
 age(26);
値の更新
• ageはko.observableでラップされている


• 値が変わると自動的に更新される

 vm = {
    name: hakurai ,
    age: ko.observable(25)
 };                                 aoshima
                                      26
 ko.applyBindings(vm);


 name = hasegawa ;
 age(26);
依存関係追跡
• オブジェクト同士に依存関係を持たせる


• ko.computed


 • 別のko.observableの値が変更されると更新される
依存関係追跡
• 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);
     }
テンプレート
 • テンプレートを利用してオブジェクトを表示する


 <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 }
                   }
<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 }
                   }
Control flow
• foreach   binding

• if   binding

• ifnot   binding

• with    binding
foreach binding
 • 配列分要素を繰り返し追加する


 <ul data-bind= foreach: users >
   <li data-bind= text: name ></li>
</ul>




                   vm = {
                     users: [{name: hoge },
                             {name: fuga }]
                   }
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 }]
                   }
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 }]
                       )
                   };
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 });
if binding
 • オブジェクトがtrueの場合に要素を追加する


 <div data-bind= if: show >
   <span>hello world</span>
</ul>




                 vm = {
                   show: ko.observable(false);
                 }
ifnot binding
 • オブジェクトがtrueの場合に要素を追加しない


 <div data-bind= ifnot: notShow >
   <span>hello world</span>
</ul>




                  vm = {
                    notShow: ko.observable(false);
                  }
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 }]
                                   }
                                 }
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 }]
                                   }
                                 }
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 }]
                                   }
                                 }
with binding
 • 入れ子構造のオブジェクトにアクセスしやすくなる


 • 大きなViewModelを複数のオブジェクトに分割


 <span data-bind= text: title ></span>
<div>
   <ul data-bind= foreach: data.users >
      <li data-bind= text: name ></li>
   </ul>
</div>
コンテキスト変数
• $parent       • $parentContext


• $parents      • $context


• $root         • $element


• $data


• $index
親のコンテキストにアクセス
• $parent       • $parentContext


• $parents      • $context


• $root         • $element


• $data


• $index
foreach中のオブジェクト
• $parent                • $parentContext


• $parents               • $context


• $root                  • $element


• $data


• $index
            配列中のインデックス
現在の要素
• $parent                    • $parentContext


• $parents                   • $context


• $root                      • $element

             <div id= item1 data-bind= text: $element.id ></div>
• $data
                                                         item1


• $index
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
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! );
                    }
                  }
click binding
• foreach中の要素の場合引数に対応するオブジェクト
 が渡される

• 基本的にevent.preventDefaultされる


 • したくない場合は関数からtrueを返す
イベントバブリング
  • data-bind中で<イベント名>Bubbleを指定する


  • クリックイベントのバブリングを止める場合

<button data-bind= click: onclick, clickBubble: false >click me</button>
小ネタ
仮想要素サポート
 • コメントを使ってバインドを指定できる


 • 引数には更新後の値が渡される

 <ul>
   <li>first</li>
   <!-- ko foreach: items -->
       <li data-bind= text: $data ></li>
   <!-- /ko -->
</ul>
ko.observable.subscribe
• ko.observableの値が変更された時に呼び出す関数を
設定できる

• 引数には更新後の値が渡される


     this.count = ko.observable(1);
     this.count.subscribe(function(newValue){
         alert(newValue);
     });
スロットル拡張
• ko.observableの値が最後に変更されてから一定時間
経った場合にUIを更新する



  vm = {
     count: ko.observable(1).extend({ throttle: 5000})
  }
  ko.applyBindings(vm);


  vm.count(2);

                 5 秒後に 2 に更新される
custom binding
• jQueryを使ったDOM操作を隠蔽したり


• 使いこなすと結構便利

  ko.bindingHandlers.<バインド名> = {
     init: function(element,valueAccessor){
         // applyBinding 時に一度だけ呼ばれる
         // 主に element に対してイベントハンドラを追加したりする
     },
     update: function(element, valueAccessor){
         // バインドしたko.observable()が変更されると呼ばれる
         // element を更新したりする
     }
  };
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便利!

More Related Content

Similar to 実践Knockout

pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングkunihikokaneko1
 
勉強会force#2 HTML5によるモバイルアプリ開発
勉強会force#2 HTML5によるモバイルアプリ開発勉強会force#2 HTML5によるモバイルアプリ開発
勉強会force#2 HTML5によるモバイルアプリ開発Kazuki Nakajima
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた Shumpei Shiraishi
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略takezoe
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -Akio Katayama
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -Akio Katayama
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方linzhixing
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼうyouku
 
20101110 Tech02 ID 管理およびサービスの設定
20101110 Tech02 ID 管理およびサービスの設定20101110 Tech02 ID 管理およびサービスの設定
20101110 Tech02 ID 管理およびサービスの設定kumo2010
 
Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Kazunari Hara
 
Jqm20120210
Jqm20120210Jqm20120210
Jqm20120210cmtomoda
 
Twitter連携chrome extension作り方
Twitter連携chrome extension作り方Twitter連携chrome extension作り方
Twitter連携chrome extension作り方Hiroshi Oyamada
 
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugSpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugY Watanabe
 
Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編なべ
 
120331 silverlight5新機能早めぐり
120331 silverlight5新機能早めぐり120331 silverlight5新機能早めぐり
120331 silverlight5新機能早めぐりTakayoshi Tanaka
 
SocialWeb Conference vol.5 OpenSocial Night #2
SocialWeb Conference vol.5 OpenSocial Night #2SocialWeb Conference vol.5 OpenSocial Night #2
SocialWeb Conference vol.5 OpenSocial Night #2Nobuhiro Nakajima
 

Similar to 実践Knockout (20)

20061125
2006112520061125
20061125
 
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
 
勉強会force#2 HTML5によるモバイルアプリ開発
勉強会force#2 HTML5によるモバイルアプリ開発勉強会force#2 HTML5によるモバイルアプリ開発
勉強会force#2 HTML5によるモバイルアプリ開発
 
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
html5j.orgがHTML5+JavaScriptで Metro Style アプリを作ってみた
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
 
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
 
Django boodoo
Django boodooDjango boodoo
Django boodoo
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
 
scala+liftで遊ぼう
scala+liftで遊ぼうscala+liftで遊ぼう
scala+liftで遊ぼう
 
20101110 Tech02 ID 管理およびサービスの設定
20101110 Tech02 ID 管理およびサービスの設定20101110 Tech02 ID 管理およびサービスの設定
20101110 Tech02 ID 管理およびサービスの設定
 
Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~
 
Grails 2.0.0.M1の話
Grails 2.0.0.M1の話 Grails 2.0.0.M1の話
Grails 2.0.0.M1の話
 
Jqm20120210
Jqm20120210Jqm20120210
Jqm20120210
 
Twitter連携chrome extension作り方
Twitter連携chrome extension作り方Twitter連携chrome extension作り方
Twitter連携chrome extension作り方
 
HTML5 on ASP.NET
HTML5 on ASP.NETHTML5 on ASP.NET
HTML5 on ASP.NET
 
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsugSpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
SpringMVCとmixer2で作るWebアプリのキホン 2013-01-24 Spring勉強会 #jsug
 
Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編
 
120331 silverlight5新機能早めぐり
120331 silverlight5新機能早めぐり120331 silverlight5新機能早めぐり
120331 silverlight5新機能早めぐり
 
SocialWeb Conference vol.5 OpenSocial Night #2
SocialWeb Conference vol.5 OpenSocial Night #2SocialWeb Conference vol.5 OpenSocial Night #2
SocialWeb Conference vol.5 OpenSocial Night #2
 

More from Kazuhiro Eguchi

なれる!クラスローダー
なれる!クラスローダーなれる!クラスローダー
なれる!クラスローダーKazuhiro Eguchi
 
Java 並行処理の基礎update1
Java 並行処理の基礎update1Java 並行処理の基礎update1
Java 並行処理の基礎update1Kazuhiro Eguchi
 
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~Kazuhiro Eguchi
 
Automate the Swing application testing
Automate the Swing application testingAutomate the Swing application testing
Automate the Swing application testingKazuhiro Eguchi
 

More from Kazuhiro Eguchi (8)

Haxe
HaxeHaxe
Haxe
 
JavaFX8
JavaFX8JavaFX8
JavaFX8
 
なれる!クラスローダー
なれる!クラスローダーなれる!クラスローダー
なれる!クラスローダー
 
Knockout
KnockoutKnockout
Knockout
 
Java 並行処理の基礎update1
Java 並行処理の基礎update1Java 並行処理の基礎update1
Java 並行処理の基礎update1
 
Starting java fx
Starting java fxStarting java fx
Starting java fx
 
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~
並行処理プログラミングの深淵~Java仮想マシン仕様 スレッドとロック~
 
Automate the Swing application testing
Automate the Swing application testingAutomate the Swing application testing
Automate the Swing application testing
 

実践Knockout