IEでDOMContentLoaded

あるHTTPレスポンスにおいて、画面の表示が遅かった(WebブラウザIEを用いていた)。
表示時には、prototype.js(1.6.0.3)を用いて、次のようにDOMツリーを操作していた。つまり、windowオブジェクトのonloadイベントのタイミングで、DOMツリーの操作を実施していた。

  Event.observe(window, 'onload', DOMツリーを操作する関数オブジェクトの参照);

つまり、次のように処理されていた(画面が二度描画されるのが、目で見て取れた)。

そこで、次のように(2番目のレンダリングを除くよう)処理を改善しようとした。

例えば、Geckoには、DOM構築が終わったときに発火するDOMContentLoadedイベントが実装されている(WebKitにも実装されているらしい)。

https://developer.mozilla.org/ja/Gecko-Specific_DOM_Events


これはいけると思い、「Prototype & script.aculo.us ―JavaScriptライブラリによるAjaxアプリケーション開発」を読んでいたら、observeメソッドのイベント名として dom:loaded が使えることを知った。だが、IE6やIE7では、DOMContentLoadedイベントが実装されていないようだ。IEの場合に dom:loaded を用いた場合にどうなるかと調べたところ、script要素のdefer属性により、JavaScriptの遅延評価を行っている(だけの)ようだ。

script要素のdefer属性を用いると、他のscript要素が全て評価された後に、defer属性があるscript要素が評価される。例えば次のようなHTMLドキュメントであれば、a.js、c.js、b.jsの順に評価される。

  <script src="a.js"></script>
  <script defer src="b.js"></script>
  <script src="c.js"></script>

しかし dom:loaded を用いても、状況は変わらなかった(やはり二度描画された)。IEでは、b.jsが実行される前に、レンダリングされるということだ。


もうだめかと思ったのだが、、次を見つけた。

http://javascript.nwbox.com/IEContentLoaded/

これには驚いた。早速試したところ、DOM構築、DOM操作、レンダリングの順で処理が実施され(レンダリングは一度だけ)、目的が達成できた。


なお、これらの話題について、以下が参考になった。

http://hisasann.com/housetect/2008/11/prototypejsdomloadedie.html