Backbone.jsのlistenToについて

  • Backbone.jsでviewの中でmodelのイベントを購読するときに「model.on("change", view.render, view)」のようなことをすると、modelからviewへの参照が残ってしまって、SinglePageApplicationやViewの切り替えを行ったりするアプリケーションではZombieViewが誕生してしまいます。
  • このような場合には0.9.9から追加されたlistenToメソッドを使って「view.listenTo(model, "change", view.render)」として「view.remove()」するといいのですが、listenToにするとどうなるのかということについてちゃんと確認してなかったので、DeveloperConsoleを使って確認してみました。

model.onの場合

viewとmodelのインスタンスを作った状態


model.onでイベントを購読した状態
  • model._eventsの中にviewがcontextとして保存されています
  • この場合、modelにしかイベントに関する情報は入ってないので、viewからは解除することができません
    • viewがmodelを持っている場合はthis.modelとして参照することは可能ですが...。


view.stopListening()した場合
  • viewからmodelへの参照は持っていないのでイベントはそのまま登録されたままです


model.off()した場合
  • model.off()することでイベントの購読を解除する必要があります


view.listenToの場合

view.listenToでイベントを購読した場合
  • _listenIdというものが購読対象(この例だとmodel)毎に発行され(この例だと"l70")て設定されています
  • さらにviewには_listeningToというオブジェクトが生成されて、その中に_listenId毎に購読対象(この場合はmodel)が入っています
  • イベントの購読自体は中でmodel.onが呼ばれているだけです


view.stopListening()した場合
  • viewから購読対象(model)を取得することが出来るので、stopListening()でイベントの購読を解除することが出来るようになっています


view.remove()でも解除できる
  • view.remove()中ではstopListening()が呼ばれているのでview.remove()すればイベントの購読を解除することが出来ます
    remove: function() {
      this.$el.remove();
      this.stopListening();
      return this;
    },


というわけでlistenToでイベントを購読することで、viewにlistenIdをキーにした購読対象(model)に対する参照が保持されるので、view.remove()の中でstopListening()が呼ばれて購読対象(model)からイベントの購読を解除することが出来るのでした