自前でアドイン(MVC Application Architecture)の仕組みを作る(その3)

次に、遅延レンダリングにまつわる描画の落とし穴を知らなかった件について。
ちなみにこの構造については自分まだちゃんと理解していませんw
こうやるとうまくいくぞ、という情報を仕入れた程度になります。
(やっぱりソース読んで理解しないとダメっすよね)


これは、Perfect Day のセミナーで小堤さんが触れてくださった為に初めて知ることができました。


今回の、タブを使ってサブアプリを表示するという仕組みは、
この遅延レンダリングがデフォルトの動作だったのが原因でした。
どんな実装をしていたのかというと、

  1. ナビゲーションエリアのボタンをクリックする。
  2. サブアプリ用の新規タブを生成。
  3. 同時にその中にサブアプリのGUIを生成。
  4. 生成した新規タブをタブパネルに追加。
  5. 新規タブを表示。


こんな感じです。が、実際には次のような挙動をしていました。

  1. ナビゲーションエリアのボタンをクリックする。
  2. 何も動作しない。(見た目的にはタブも生成されていない)
  3. もう一度ナビゲーションエリアのボタンをクリックする。
  4. 正常に新しいタブが表示される。(サブアプリも正しく表示される)

という何がなんだかわからない状態でした。



ところで、ExtJSはリソース節約とパフォーマンス向上のため、
必要になった時点でインスタンス化したりレンダリングする機構をデフォルトで備えています。
それらを「遅延インスタンス化」「遅延レンダリング」と言うようですが、
このおかしな現象の原因が「遅延レンダリング」にあるらしいと。

遅延レンダリングは、

  1. インスタンス化されているのでメモリ上には存在するが、
  2. まだHTMLとしては生成されておらず、
  3. ユーザの操作でそのオブジェクトを表示させようとしたタイミングで、
  4. HTMLとして描画を行う

ことを差します。

ここからは自分の単なる推測なのですが、
インスタンス化されている時には「Render」に相当するものがメモリ上に生成され、
ユーザが描画させるための操作をしたときにRenderが「HTMLのDOM」を生成する、
という感じだと思います。

さて、この観点から発生していた現象を考察すると・・・って思ったんですが、
ソースも読まないで推測してもあんまり意味が無いので止めますw


で、核心の小堤さんから教えていただいたキーワードは、

deferredRender

というconfigオプションです。
明示的に「遅延レンダリング」か「即時レンダリング」を指定することができます。
deferredRenderをfalseに指定すると、「即時レンダリング」にしてくれるそうです。
deferが延期するって意味ですからね。
ちなみに、購入したExtJS実践開発ガイドのP.99にもそのものズバリという情報が思いっきり記載されていましたw

なので、解決するには、メインエリアのタブを定義するときに次のようにdeferredRenderを指定します。

Ext.define(
    'Sample.view.TabPanel',
    {
	extend: 'Ext.tab.Panel',
	deferredRender: false,

	// 中略
    }
);

これで3ヶ月解けなかった問題がすべて解けました。
ありがとうございましたー。