新卒から文系エンジニア→人材業界に転職した人のブログ

新卒から文系エンジニア→人材業界に転職。技術・スキルがないためブログを通して勉強。その後、IT業界の業界知識が活かせる人材業界へ。異業種×異職種の転職経験有り。

このエントリーをはてなブックマークに追加

【javascript】javascriptのDOMイベントの実行順序 各フェーズ(キャプチャフェーズ・ターゲットフェーズ・バブリングフェーズ)

■今回の紹介

addEventListenerについて調べていて、
addEventListenerの第三引数(以下の?部分)について、意味がよくわからなかったため、調べたものをメモしときます。

☆addEventListener
 用途 :同一ノードに同一イベントに複数のfunctionを登録すためのもの
 使用例:document.addEventListener('click'(イベント名) , listener(実行関数名),?(false or true);

■補足

 同じく、DOMにイベントを登録する方法は、いくらかある
HTMLべた書き

<p onclick="console.log('p');" style="border:5px solid black;">text</p>   


DOM要素のプロパティに直接登録
 例

<p id="p2" style="border:5px solid yellow;">text2</p>
   var a = document.getElementById("p2");
    a.onclick = function () { console.log('p2'); }

■内容


話を戻すと、addEventListenerの第三引数である
useCaptureにtrue or falseを設定することにより何が変わるのか何を設定するのかわからなかったわけです。

この問いの結論を先に言うと

追加されたDOMのイベントの実行順序(タイミング)を指定する

というものでした。

まず、以下のサイトでは、
addEventListenerの第三引数であるuseCaptureについて以下のような説明があります。

引用元:js.studio-kingdom.com

<引用文>
以下の参考サイトでは、このような説明がありました。
trueを指定すると、useCaptureはユーザーがキャプチャ開始を望んでいることを指し示します。
キャプチャ開始後は、イベントがDOMツリー内のそのEventTarget下に送られる前に
指定されたtypeの全てのイベントが登録されたリスナーに送られます。
ツリーを通してバブルアップ(浮上)するイベントは、useCapture指定されたリスナーをトリガしません。
詳細については、DOM Level 3 Eventsを参照してください。
指定されない場合、useCaptureはデフォルトのfalseを適用します。
<引用文>




上記の説明を理解するためには、

「基本的にDOMのイベントがどのような順序で実行されるのか」

 
というのを知る必要がありました。


■DOMの構造について

基本的にDOMの構造はツリー上になります。
たとえば
 html
  |-body
|-div
|-p
|-a
|-br



■イベントの実行順序について

 たとえば、
  ・pにonclickにイベントが設定されている
  ・pの要素をクリックする

 その際、以下のように実行されます。
 html⇒body⇒div⇒p  これをキャプチャフェーズという
 p⇒div⇒body⇒html  これをバブリングフェーズという



つまり、上記のようなイベントのフェーズの流れが前提で、
useCaptureを設定することにより、イベントの伝搬をどのような順序で拾うかということを設定していました
true ⇒キャプチャフェーズ
false⇒バブリングフェーズ
 となります。



※この設定の用途としては、あるノードの内側だけイベントを実行したい、外側だけ実行したいという
制御を行うことが可能になります。

参考サイト:図が非常にわかりやすい!qiita.com



■以下はサンプルです。


☆共通

<body id="body" style="border:5px solid black;">
  <div id="div"style="border:5px solid red;">
    <p id="p" style="border:5px solid black;">text</p>   
  </div>
</body>


■キャプチャフェーズのサンプル
 以下のサンプルでは、pをクリックした際は、
 親ノードbodyから子ノードpという順序で、実行されます。
 これをキャプチャリングといいます。

結果:p要素選択時、
1.BODYのイベントですP要素で拾っています
2.PのイベントですP要素で拾っています

    var body = document.getElementById("body");
    var div = document.getElementById("div");
    var p = document.getElementById("p");

    body.addEventListener('click', OutLog, true);
    p.addEventListener('click', OutLog, true);

    function OutLog(e) {
        console.log(e.currentTarget.tagName +"のイベントです" + e.target.tagName + "要素で拾っています");
    }

■バブリングフェーズのサンプル
 以下のサンプルでは、pをクリックした際は、
 子ノードpから子ノードbodyという順序で、実行されます。
 これをバブリングといいます。

結果:p要素選択時、
1.PのイベントですP要素で拾っています
2.BODYのイベントですP要素で拾っています

    var body = document.getElementById("body");
    var div = document.getElementById("div");
    var p = document.getElementById("p");

    body.addEventListener('click', OutLog);
    p.addEventListener('click', OutLog);

    function OutLog(e) {
        console.log(e.currentTarget.tagName +"のイベントです" + e.target.tagName + "要素で拾っています");
    }
.hatena-module:nth-of-type(10) { background: transparent; } .hatena-module:nth-of-type(10) .hatena-module-title{ display: none; } .hatena-module:nth-of-type(10) .hatena-module-body { padding: 0; }