プロが教える店舗&オフィスのセキュリティ対策術

お世話になります。DOMContentLoaded の使い方について教えて下さい

以下のURLページに
「DOMContentLoaded イベントは、最初のHTMLドキュメントの読み込みと解析が完了した時に、スタイルシートや画像、サブフレームの読み込みが終わるのを待たずに発火します。」

https://developer.mozilla.org/ja/docs/Web/Events …

とあります。

上記の説明によると「DOMContentLoaded」がある場合と、ない場合の差はコードが実行されるタイミングだけだと思います。

具体的にいうと、先にコード全体を読み込むような場所(HTMLのヘッダー部)に<script>を配置した場合、先にコードを読み込むので「DOMContentLoaded」はあってもなくても動作に影響しないと思います。

なので、試しにガイドブックにあるサンプルコードから「DOMContentLoaded」を
「ZZZ」に変更したところ、動作しなくなりました。

私の感覚では「最初のHTMLドキュメントの読み込みと解析が完了した時に、スタイルシートや画像、サブフレームの読み込みが終わるのを待たずに発火します。」

というわけですから、HTMLのヘッダー部に<script>を配置した場合、
先にコードが読み込まれるので「DOMContentLoaded」はあってもなくても
動作に全く影響しないと思うのですが、なぜ動作しないのでしょうか?

コンソールにはエラーメッセージが出力されないのでコード的には間違いはないと思います。
なのになぜ、以下のコードではキャンセルのイベントが発生しないのでしょうか?

お手数ですが詳しい方、説明の上手な方、以下のコードでキャンセルイベントが発生しない理由を教えて下さい。よろしくお願いします。

<head>
<script>
window.addEventListener ("ZZZ",function() {
var BBB = document.getElementById("AAA");
BBB.addEventListener("click", function(CCC){
//既定のイベントをキャンセル
CCC.preventDefault();
window.alert("ダイアログボックスの中!");
} );
} );
</script>
</head>

<body>
<a href="http://www.google.co.jp" id="AAA">google</a>
</body>

※「ZZZ」を「DOMContentLoaded」に変更するとイベントは実行されます

A 回答 (2件)

こんにちは


いくつか誤解があるようです。

>HTMLのヘッダー部に<script>を配置した場合、先にコードを読み込むので>「DOMContentLoaded」はあってもなくても動作に影響しないと思います。
スクリプトだけで完結している処理であれば、ご理解の通りですが、DOMを操作するような内容のスクリプト(質問文に例示されているものも該当)の場合は、実行時にはまだ<head>部分を解釈中ということになります。
従って、DOMが構築された状態ではありませんから、大抵その処理は失敗(=エラー)することになります。
そのようなことを避けるために、「DOMContentLoaded」を利用することで、DOM構築を待ってから処理を実行するという順序を確実にすることが可能になります。

>サンプルコードから「DOMContentLoaded」を
>「ZZZ」に変更したところ、動作しなくなりました。
addEventListenerの第一引数は「イベントの種類」を示します。
「ZZZ」なるイベントはデフォルトでは存在しませんので、発生することがないので、指定された関数が実行されないだけです。
https://developer.mozilla.org/ja/docs/Web/API/Ev …
(ZZZをユーザー定義のイベントとして利用することは可能ですが、それには定義やイベントの発火の処理が必要になります)
必ず発生するであろうイベント(例えば「load」など)に変更すれば、同様の動作になるはずです。


>以下のコードでキャンセルイベントが発生しない理由を教えて下さい。
上記の説明の様に、ZZZイベントが発生していないので、匿名関数が実行されることはありません。
ですので、id=AAAの要素にイベントをバインドすること自体が行われていないため、クリックしても何も処理は行われないことになります。

なお、preventDefault()メソッドは「イベント」ではありません。
当該イベントのデフォルトの動作を停止(キャンセル)するメソッドです。
(リンク要素のクリックの場合、遷移動作が行われなくなるなど…)
https://developer.mozilla.org/ja/docs/Web/API/Ev …
むしろ、引数として受け取ろうとしている変数CCCの内容が、イベントオブジェクトです。
しかしながら、実際には、定義が実行されていないので動作することはありませんけれど。
    • good
    • 1
この回答へのお礼

ありがとう

お礼が遅くなりすいません。
丁寧に解答して頂きありがとうございます。

微妙な誤解がたくさんあるので
1つづつ説明して頂いて助かりました。

今回は丁寧に教えて頂きありがとうございます。
機会がありましたら、またお願いします。

追記
自分の忘備録をかねて、このページ上で軽くまとめました。

~~

>HTMLのヘッダー部に<script>を配置した場合、先にコードを読み込むので>~
スクリプトだけで完結している処理であれば、ご理解の通りですが、~実行時にはまだ<head>部分を解釈中ということになります

意外で、びっくりです。
No.1さんのお礼にも記載しましたが、
私の解釈で「HTMLの読み込み = レンダリングの完了」と思っていたので、
このあたりの言葉の意味が微妙にズレていました。

>サンプルコードから「DOMContentLoaded」を~
>「ZZZ」に変更したところ、~必ず発生するであろうイベント(例えば「load」など)に変更すれば、同様の動作になるはずです。

そうなんですね。「load」で試してみたところ、ご指摘のとおり動作したので納得しました。
https://www.sejuku.net/blog/19754

>以下のコードでキャンセルイベントが発生しない理由を教えて下さい。~id=AAAの要素にイベントをバインドすること自体が行われていないため~

気が付きませんでした。
匿名関数に慣れていないので「id=AAA」にバインドする必要があるとは気が付きませんでした。

>なお、preventDefault()メソッドは「イベント」ではありません。
当該イベントのデフォルトの動作を停止(キャンセル)するメソッドです。~
>むしろ、引数として受け取ろうとしている変数CCCの内容が、イベントオブジェクトです。

ご指摘ありがとうございます。ガイドブックを確認したところ、

「preventDefaultメソッドを実行することで『aタグでクリックイベントが発生した際に画面を遷移する』
という本来のイベントがキャンセルされ、アラートを表示する処理が実行されます。」

とありました。

~~

どれも微妙な勘違いなので、
丁寧に説明して頂き助かりました。

今回は解答して頂きありがとうございます。
機会があれば、またお願いします。

お礼日時:2019/01/16 23:16

ロード時に動かすことができるのは3段階あります



・即時処理
・DOMContentLoaded
・Load

即時処理はHTMLの構造が読み込まれていなくても実行されるので
一番早いですが、そのスクリプト以降に書かれたHTMLにアクセスができません

DOMContentLoadedはHTMLが読み込まれたあとなので、
HTMLにアクセスできますが、レンダリングされていませんので
たとえば段落の幅などを参照することができません

Loadはすべてが確定してから実行されます

三者三様でメリット・デメリットがあります
    • good
    • 1
この回答へのお礼

Thank you

解答して頂きありがとうございます。

>
DOMContentLoadedはHTMLが読み込まれたあとなので、
HTMLにアクセスできますが、レンダリングされていませんので
たとえば段落の幅などを参照することができません

HTMLの読み込み = レンダリングの完了だと思っていました。

ですが「HTMLの読み込み = レンダリングの完了」
だったらLoadと同じになってしまいますね。

気が付きませんでした。

今回は解答して頂き、ありがとうございます。
機会があれば、またお願いします。

追記
No.1さんが詳しく説明してくれているので、
No.1さんの解答をよく読み、改めて確認する予定です。

No.1さんへのお礼、etc.は夜以降になります。

お礼日時:2019/01/16 12:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!