Backbone.jsで書き始めて3日目ぐらいです。どうも。
唐突ですが、以下のようなモデルが存在するとします。
var HogeModel = Backbone.Model.extend({
defaults: {
foo: 0,
bar: 0
},
increment: function(){
// 変更の通知を1回だけにしたい…
this.set('foo', this.get('foo') + 1, {silent: true});
this.set('bar', this.get('bar') + 1, {silent: true});
this.trigger('change');
}
});
簡単なHogeModelです。
続いて、これまた唐突にViewを作ります。HogeViewでいいや。
var HogeView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, 'render');
this.model.on('change', this.render);
},
render: function(){
this.model.increment(); // この段階で、render()が無限ループ
this.$el.html(this.template(this.model.toJSON()));
}
});
さらりと書き、実行したら動きませんでした。
何でだろうと思ったら、以下の通り。
- HogeModelのプロパティをset()で更新
- HogeViewでrender()される前に、パラメーターを+1する
- increment()でtrigger('change')で一気に更新しようとする
- HogeModelにchangeイベントが走るのでHogeViewのrender()が走る
- 無限ループの完成
- そして考えるのをやめた
なんで silent:false だと上手くいっていたんだろう…。と思ったら、
trigger('change:foo') 、trigger('change:bar') という形のイベントを発火しているという感じでした。
どうしようと思って直した(ように見える)コードがこちら。
var HogeView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, 'render');
this.model.on('change', this.render);
},
render: function(){
this.model.off('change', this.render);
this.model.increment(); // 無限ループにならない!!
this.model.on('change', this.render);
this.$el.html(this.template(this.model.toJSON()));
}
});
一旦Modelのイベントを削除、処理して更新後に、イベントを再設定しました。
まぁ、なんのことはない感じなわけですが、これにそこそこ(1時間)ぐらい悩んでた気がします。
似たようなことがあった人はお試しあれ、です。
// そもそも、もっとうまい書き方があるんではなかろうか?