BakboneJSだってDOMとModelをBindingしたい！

BakboneJSだってDOMとModelをBindingしたいッッ
===

    JavaScript - Client Side - Advent Calendar 2013
    http://qiita.com/advent-calendar/2013/javascript  
    12/3(火)分の記事です。


 さてさて
--

Backbone.jsを使うとjQueryのみ使うより
Webアプリケーションのソースコードが
スッキリ書く事が出来ますよね。

「よーし、もっと勉強するぞ〜」っと思っていると
最近、AngularJSが超人気なんで嫉妬してます。

特にData Bindingうらやましい...

>  
Data-binding is an automatic way of updating the view whenever the model changes, as well as updating the model whenever the view changes. 
http://angularjs.org/

<br />
そこでBackbone.jsに Data-binding機能を追加出来ないかライブラリを探してみました。

 
derickbailey / backbone.modelbinding
---
https://github.com/derickbailey/backbone.modelbinding
Star★： 730  


theironcook / Backbone.ModelBinder
---
https://github.com/theironcook/Backbone.ModelBinder
Star★： 1,145
    

mikeric / rivets
---
https://github.com/mikeric/rivets
Star★： 1,230

NYTimes / backbone.stickit
---
https://github.com/NYTimes/backbone.stickit
Star★： 815

...結構いっぱい有りますね。

今回は **Backbone.ModelBinder** を使うと
どんな感じに便利なのか使わない場合と比較してみたいと思います。


作成アプリ例
---
![bb_mb.png](https://qiita-image-store.s3.amazonaws.com/0/5793/bb6697e7-96af-8f0f-30a8-f9ba0fbd1806.png "bb_mb.png")


左側の連絡先一覧の描画で比較してみたいと思います。

まずBackbone.ModelBinderを使わないで...
---


```js:一覧生成：JavaScript
var AddressListView = Backbone.View.extend({
    // ... 省略 ....
    createRender: function(){
        this.addressList.each( this.createOneRender, this);
    },
    createOneRender: function( address){
        var addressItemView = new AddressItemView({
            address: address,
            addressList: this.addressList
        });
        addressItemView.createRender();
        this.$('.js-list').append(addressItemView.$el);
        
    }
});
```
一覧がく〜るくるとcreateOneRenderで明細生成します。

<br />

```js:各明細：JavaScript
var AddressItemView = Backbone.View.extend({
    tagName: 'li',
    initialize: function(options) {
        this.address = options.address;
        this.listenTo(this.address, 'change', this.updateRender);
    }
    createRender: function(){
        this.$el.append('<div class="js-item-name item-name"></div>');
        this.$el.append('<div class="js-item-kana item-kana"></div>');
        this. this.updateRender();
    },
    updateRender: function(){
        this.$('.js-item-name').text( this.address.get('name') + '様');
        this.$('.js-item-kana').text( this.address.get('kana'));
        return this.$el;
    }
});
```
比較ポイントは  *this.address* の *change* イベントを監視し
*updateRender* で更新している箇所です。

<br />
Backbone.ModelBinderを使う！
---

```js:各明細：JavaScript
var BinderAddressItemView = Backbone.View.extend({
    tagName: 'li',
    initialize: function(options) {
        this.address = options.address;
        this.addressList = options.addressList;
        
        // Backbone.ModelBinderを使うぞ！
        this.modelBinder = new Backbone.ModelBinder();
        
    },
    createRender: function(){
        this.$el.append('<div class="js-item-name item-name"></div>');
        this.$el.append('<div class="js-item-kana item-kana"></div>');
        
       // DOMとModelのbind設定
       // 左側 Modelの属性名
       // 右側 DOMを探すセレクタ名、データ表示時のフォーマット  
        var bindings = { 
            name: {selector: '.js-item-name', converter: this.nameConverter},
            kana: {selector: '.js-item-kana' }
        };

       // DOMとModelのbind開始！
        this.modelBinder.bind(
            this.address,
            this.el,
            bindings );

    },
    
    // 名称表示時のフォーマット
    nameConverter: function(direction, value){
        if ( direction ){ return (value + '様'); }
        return value;
    }
});

```

initializeの所にBackbone.ModelBinderの生成を追加して

```js
this.modelBinder = new Backbone.ModelBinder();
```

createRenderで生成したDOMにBackbone.ModelBinder#bindでModelを紐づけてます。

```js
this.modelBinder.bind(
    this.address,
    this.el,
    bindings );
```

フォーマット記述も可能な様子。
directionは Model -> View の時に trueが入ります。

```js
nameConverter: function(direction, value){
    if ( direction ){ return (value + '様'); }
    return value;
}
```


まとめ
---

あッ、あれッ、むしろソースが長くなった？？(^^;;
前の方が良くない？って思いました。

でもですね、ModelとViewのDataBindingがあると
人によるソース記述差異が少なくなって良いのではと思います！

Marionetto.jsと合わせて勉強していきたいですね。


サンプルソース
---
https://github.com/itokami1123dev/Backbone_ModelBinder_sample