Backbone.js

ゾンビView問題~Backbone-supportでSwapping RouterとCompositeViewを使う

投稿日:2013年2月6日 更新日:

ゾンビView問題

Backbone.jsでページ遷移を行うとき、今まで使っていたViewはどこに行ってしまうのか

その謎は僕らにも解明できていないんだ

 

ホントは、Backbone.jsはViewの使い方についてメモリ管理機構をもってないので、明確に開放しないとメモリを圧迫したり、予期しない動作を起こしたりすることがある

たまたま、そんな現象がカメラに撮影できたので観てもらいたい

これはコレクションへのaddの監視が2重、3重に設定されちゃうので起こってるっぽい現象

こういったことを避けるには簡単で設定してるイベント類をちゃんと開放?(unbind)してから次の動作に移ればいい

開放するものは3つくらいあって、1.DOMと2.それに渡されたモデルやコレクションのイベント、3.view独自のイベント(イベントハッシュでバインドしたイベント)だ

DOMの開放は一番簡単で

モデルやコレクションのイベントはonを使っていればoffすればいい(最近できたListenToとかがどういうメリットがあるのかまだよくわかってない)

view独自のイベントは

すればいい

*最近(0.9.9~)の問題は最後に追記

 

ただ、Backboneを使うような複雑なたくさんのViewを使うようなアプリで1個1個これをやっていくのかというと、それってプログラマっぽくないし、1個でも忘れてたらバグ取りで死ぬよね!?

で、これを防止するためのアイデアの1つがComposite ViewとSwapping Router

これは有料のThoughtBotの本に詳しい解説があるんだけど、gemとしてGithubに公開されているから、そのREADMEとソースをみればだいたい分かることだけ紹介したい

github.com/thoughtbot/backbone-support

使う準備は簡単

Gemfile

で、application.jsに次の1行を追加

Composite View

Composite ViewはBackbone.Viewを継承した抽象クラスとして使うことが想定されていて、Backbone.Viewの代わりにextendして(coffeeならextendsして)使う

その機能の第1がすべてのViewにleave()メソッドを提供すること.leave()ってやるだけで全部終わらせてくれるようになっている(らしい).

第2に、子どものViewを追加したり、除去したりするための便利なメソッドがついている

そして、親Viewが子どもViewを配列で管理していて、子どものViewもleave()で一気に全部終わらせてくれる.

github.com/thoughtbot/backbone-support/blob/master/lib/assets/javascripts/backbone-support/composite_view.js

Composite Viewを使ってネストしたViewを作るときのTips

例えば、親Viewで大まかなLayoutをdivで作って、そのdivに子Viewで部品をくっつけていく場合

例:親テンプレート(ここの#article_formにフォーム部品をくっつけたい)

@$(‘selector’)(JavaScriptではthis.$(‘selector’)というイディオムを使うメソッドを使う

backbonejs.org/#View-dollar

stackoverflow.com/questions/7113049/backbone-js-nesting-views-through-templating

例:

renderChildIntoはcompositeViewのメソッドなんだけど、やってることは、$(container)を空にして、elをくっつけるだけ(あとchildrenリストに加えたり、親が誰かを記録したりしてる)

renderChildIntoのソース

ほかにも、compositeViewにはappendChild, appendChildTo, prependChild, prependChildToとかわかりやすいメソッドがある

ここの文書はないのでソースをみればだいたい使い方はわかるはず

Swapping Router

Swapping RouterはBackbone.Routerを継承していて、普通のRouterの代わりに使う

Swapping Routerはswap(newView)というメソッドを提供してくれる

github.com/thoughtbot/backbone-support/blob/master/lib/assets/javascripts/backbone-support/swapping_router.js

これは前のViewをleave()して、@currentViewという変数を使いまわしてくれるので、新たなメモリ空間を使わないという仕組みになっている

 

(;・∀・)ハッ? これが円環の理か(結局、これが言いたかった)

 

SwappingRouterの使い方

継承する

 

elを決める

 

swap(view)メソッドを使う

 

いろいろ

ほかの方法

参考

Backbone.marionette

画面遷移のあるアプリで、Backbone.Viewを使っていた場合のイベントとか後始末

 

listenTo

最近(0.9.9~)ではlistenToを使うと自動的にthis.remove()でstopListening()が呼ばれるようになったので、this.remove()でモデル・コレクション関係のイベントを止められる

なら今後はthis.remove()だけ忘れなければなんとかなるのかも

Backbone.js 0.9.9 のChangelogを適当に日本語訳してみた

backbonejs.org/#Events-listenTo

 

removeのときに自動でundelegateEventsを呼ぶべきだという議論

独自のイベント(delegateEventsっていうらしい)はundelegateEvents()で消すらしい

backbonejs.org/#View-undelegateEvents

Backbone.View remove should call undelegateEvents

どうもDOMをremoveしたからといって、undelegateEventsの必要がないとは言えないらしい

backboneはjQueryに依存してなくて、ほかのライブラリを使ってる人もいるからなかなか難しいっぽい

backbone-mediatorっていうpub/subで解決してる例がある(まだよく理解してない)

 

setElementメソッドが賢くundelegateEventsしてくれるらしい

SubView的なモノのより良い管理方法 (Backbone Advent Calendar 2012 24th day)

たしかにソースコードにコメントがあった

// Change the view’s element (this.el property), including event
// re-delegation.

setElementの使いドコロがよくわかってない

github.com/enja-oss/Backbone/blob/master/docs/View.md

BackboneのViewを違うDOM要素に適用したい場合、 setElement を使用します。このメソッドは$elの参照をキャッシュして、Viewがもつイベントの委譲を古い要素から新しい要素に移動させます。

上のページではサブViewを使うとき下みたいにすれば何度もnewしなくていいって(なるほど)

こっちでは

stackoverflow.com/questions/9586279/using-setelement-with-views-in-backbone

setElementでthis.elがキャッシュされるので、後ろのrenderでthis.$elが使えるようになるって言ってる

 Backbone.js (Sub)View Rendering Trick

Backbone.Eventsはleave()だけじゃだめ

Backbone.Eventsはちゃんとoffしないとダメ

1回目はいいけど2回目に不審な動きやエラーがでるみたいなバグはゾンビを疑った方がいいかもしれない.

 

 

-Backbone.js
-,

執筆者:

関連記事

backbone-railsのscaffoldで生成されるコードでルーティングとCRUDの処理をどうやってるのか読んでみた

By: asobi tsuchiya   目次1 はじめに2 サンプルの準備3 初期化4 ルーター5 READ6 CREATE7 UPDATE8 DELETE はじめに backbone-r …

Rails3.2とBackbone.jsでGoogle CalendarライクなカレンダーにCRUD~fullcalendar-rails

目次1 前回2 READ ~データベースからイベントを読み込んでカレンダーに表示する3 CREATE~カレンダーからイベントを登録する4 UPDATE1~カレンダーのイベントをクリックしてイベントを編 …

no image

Backbone.jsでGooleアカウントにOAuth2でログインしてGmailのタスクリストと同期するToDoリストをつくるというチュートリアル

dailyjs.com/2012/11/29/backbone-tutorial-1/ たぶんまだ4割くらいしか理解できてない JavaScriptで、nodeのhttpサーバとgrunt.jsで圧縮 …

Backbone.js0.9.10以降のクライアントサイドでのvalidate

ThoughtBotの『Backbone.js on Rails』の目次と見出しをななめ読み

By: John – CC BY 2.0 learn.thoughtbot.com/products/1-backbone-js-on-rails 買いました 電子書籍で137ページに$4 …