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

  • 12
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

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/



そこで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

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

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

一覧生成: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で明細生成します。


各明細: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.addresschange イベントを監視し
updateRender で更新している箇所です。


Backbone.ModelBinderを使う!

各明細: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の生成を追加して

this.modelBinder = new Backbone.ModelBinder();

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

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

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

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

まとめ

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

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

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

サンプルソース

https://github.com/itokami1123dev/Backbone_ModelBinder_sample