2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Modelのchangeイベント時の処理に悩んだ結果

Last updated at Posted at 2014-02-07

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時間)ぐらい悩んでた気がします。
似たようなことがあった人はお試しあれ、です。

// そもそも、もっとうまい書き方があるんではなかろうか?

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?