JavaScript スキルアップ

【JS】 DOMContentLoaded と load の違いを新人でもわかるように解説

JSのイベントリスナーでDOMContentLoadedとloadがあるけど何が違うんだろう?どう使い分けたらいいんだろ?

JSイベントの設定でよく見かけるDOMContentLoadedとloadがありますが、それぞれ違いを理解した上で使い分けられていますでしょうか?

この二つの違いは発火のタイミングです。
この理解が無いと想像通りの挙動をしてくれないことがあります。

では詳しく解説していきます。

Webページの読み込み順を理解しよう

細かいところ解説していくと長くなるので、とりあえずこの2段階を知っていれば大丈夫です。

①DOMツリーを読み込む
②画像、CSSなどの外部ファイルの読み込み完了

①の時に全てのHTMLタグを樹形図のように表し、その構造(テキスト情報も含む)を書き出します。
まずページ全体の骨格を作っていると思っておいてOKです。

②ではその骨格の形成が完了した後に使われている画像やCSSを読み込んでページを完成させていきます。

ネット環境がめちゃくちゃ悪いところで何かのページを見ると、まず文章構造(文字や改行)だけが反映されて、その後にCSSが適用されて画像が読み込まれますよね。
これは重要なポイントです。

では本題に入っていきましょう。

DOMContentLoadedはDOMツリー読み込み完了後に発火

DOMContentLoadedはDOMの読み込みが完了してから発火します。

document.addEventListener('DOMContentLoaded',
  function(){
    console.log('DOMツリーの解析が終わりました。');
  }
);

上記の場合DOMツリーの読み込みが終わって、画像やCSSが読み込まれる前に「DOMツリーの解析が終わりました。」と出てきます。

ここで知っていて欲しいことは、
<script>タグの読み込みはHTMLの</body>直前に記述する場合、改めてDOMContentLoadedの設定は不要ということです。
なぜかというと、

Webの仕組みでページの読み込みはHTMLファイルの上から順番に読み込んでいくので、
HTMLの下部に<script>タグ入れておくと、<script>タグが読み込まれるまでにすでにDOMの読み込みが完了しているからです。(正確には<script>タグ以降に他の閉じタグの2,3行は残っているかもですが)

したがって、わざわざDOMの読み込み完了後に「DOM読み込み完了時にイベント発火させる」という記述は不要なのです。
だって対象のJSファイルが読み込まれる時にはもうDOMの読み込み終わってるんだし。

逆にDOM操作をするJSを<head>の中に書いている場合はDOMContentLoadedを使っていないと、エラーになる可能性があります。後述しますがloadイベントでも大丈夫です。

理由はDOM読み込みが終わっていないのにDOM操作をしようとするからです。
その状態では操作対象のDOMはNull(なにもない)になって返ってきます。

JS:「さぁ、DOMを操るぞー!、、あれ?目当てDOMが見つからない,,,??」
HTML:「だってまだDOMを全部読み切ってないもん。
JS:「そっか。じゃあNull出しとく!

みたいな感じです。

<head>にJSを記述する際の注意点は、JSの読み込みが完了しないとHTMLの読み込みも再開されないという点です。
よって長いJSの記述をしているとページ表示に時間がかかってしまいユーザーの離脱に繋がる可能性があるので気をつけましょう。

loadはDOMContentLoadedよりも後に発火

loadイベントはDOM読み込みだけではなく、画像やCSS等の外部ファイルもすべて読み込みが完了してから発火します。
よって「load」の方が「DOMContentLoaded」よりイベントの発火タイミングが遅いです。

こんな順序でイベントが発火します。

window.addEventListener('load', function(){
  console.log('ページの読み込みが完了しました。');
});

こうすると、DOMツリーの読み込みが終わってかつ、画像も完全に読み込みが終わってから「ページの読み込みが完了しました。」と表示されます。

例えばページ読み込み時にローディングを実装して、ページが完全に読み込こまれたらそのローディングを消すとかに使えそうですね。
こんなやつ↓↓

実際にDOM ContentLoadedとloadの発火タイミングを比較してみましょう。

window.addEventListener('load', function(){
  console.log('ページの読み込みが完了しました。');
});

document.addEventListener('DOMContentLoaded',
  function(e){
    console.log('DOMツリーの解析が終わりました。');
  }
);

このように記述すると、本来は上から順番に実行されるので、
①「ページの読み込みが完了しました。」
②「DOMツリーの解析が終わりました。」
の順に表示されるかと思います。

ですが、実際は
ページの読み込み完了の方がDOM解析より時間がかかるので、
①「DOMツリーの解析が終わりました。」
②「ページの読み込みが完了しました。」
の順番に表示されます。

検証結果↓

ちなみに、
loadイベントだとwindow.addEventListener
DOMContentLoadedイベントだとdocument.addEventListener
と記述されておりwindowとdocumentの部分が違っています。
これはそれぞれのイベントがwindowオブジェクトとdocumentオブジェクトに対して動作しているからです。

ここではサラッとだけ解説します。
windowオブジェクトとはJSが動作しているブラウザのwindowを指しています。
documentオブジェクトとはDOMを指しています。

loadイベントがwindowとなっているのはページロード自体がブラウザ全体に関係しているからです。
一方、DOMContentLoadedイベントはDOM関連の読み込みだけが必要なのでdocumentとなっています。

今回は以上となります。
皆さんのJSの理解に繋がっていれば幸いです。
では!

あわせて読みたい

【2024最新Udemy】Web開発フロントエンドにおすすめ講座10選!Web制作初心者中級者向け

続きを見る

あわせて読みたい

【2023最新】Web制作フロントエンドおすすめ本9選!基礎から応用まで学ぶ

続きを見る



知って得する

【30代未経験】エンジニア転職に必要なスキルと入社後の業務を元エンジニア採用担当が解説します

続きを見る

-JavaScript, スキルアップ
-, , , ,