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 を使うと
どんな感じに便利なのか使わない場合と比較してみたいと思います。
作成アプリ例
左側の連絡先一覧の描画で比較してみたいと思います。
まずBackbone.ModelBinderを使わないで...
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で明細生成します。
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 で更新している箇所です。
Backbone.ModelBinderを使う! ---
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と合わせて勉強していきたいですね。
サンプルソース