自分で調べたこと、はまったことのまとめ。
調べたこと
Backbone
そもそも Viewとかに disposeがない。頑張って自分で管理。そこらへん Chaplin偉い。
Controller
Controllerは dispatchごとに新しいのが作り直される。これは、Dipatcherのなかで以下の順で行われる。
- newController.beforeAction()
- oldController.dispose(param, route, option) # ここで後述のように Viewが捨てられる。
- dispatcher.currentController = newController
- newController.action(...) # router で指定された action。普通の Viewはここで作って member変数に入れておく。
- dispatcher.publishEvent 'dispatcher:dispatch' # ここで Composer#cleanupが走る
View
Controllerとともに disposeされるべき Viewは Controllerの member変数に入れておけ。そうすれば、Controller#disposeが捨ててくれる。
逆に、捨てられては困る Viewなどは入れてはいけない。
ちなみに Backboneの Viewは階層構造をもたない。chaplinでは subviewを使って階層構造を作ることができる。当然、親の Viewが disposeされたときに subviewも一緒に disposeされる。
普通 Viewが disposeされたら、対応する DOM要素もなくなる。
Compose
複数の Controllerをまたいで生きる Viewは、Composerに管理してもらう。そうすれば無駄な DOM再生成、再描画を抑えられる。
Composer経由で作られた Viewは、cacheされ、次の Controllerに遷移した時に再利用できるなら再利用される。再利用されない Viewは、action (routerで指定された method) を実行する前に Composer#cleanup経由で disposeされる。
再利用できるかどうかは、通常 compose時に渡した optionが同じものかどうかで判定される(Composition#check)。判定方法も options.checkで変えられそうだけど使ったことなし。
ハマったこと
複数の composeされた Viewの階層
注意することとして、DOM階層が複数の composeされた Viewによりできてた場合、根の Viewだけが再利用不能とされ再構築されると変なことになる。枝の Viewは renderされず DOM部分木も根に繋ぎ直されないので、根の Viewだけ画面に現れることになる。
callback中は、controller.compose 'id' で view を見つけられない
Composer#cleanupでは、生き残った Viewも staleフラグを立てられ、以降の Composer#retrieveで無視される。つまりdispatcher:dispatchイベントの後に callbackが呼び出されたりすると、そこでは controller.compose 'id' では viewを見つけられない。