2021-01-06に投稿

EventTargetとは

読了目安:10分

EventTargetはイベントのターゲットとなるオブジェクトです。
イベントリスナーの登録や削除を行えます。

EventTargetのメソッド

addEventListener - イベントリスナの登録

addEventListenerの第1引数にイベントの名称、
第2引数にイベント発生時に実行する関数を指定する事でイベントの登録が行なえます。

例えば、クリックのイベントは以下のように登録できます。
buttonAをクリックするとdiv要素のクリックイベントも呼び出されます。

<div id="outer">
  <div id="inner">
    <button id="buttonA">A</button>
  </div>
</div>
document.getElementById('outer').addEventListener('click',function(){console.log('outer');});
document.getElementById('inner').addEventListener('click',function(){console.log('inner');});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA');});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');});
//buttonAをクリックする => buttonA buttonA2 inner outer

第3引数としてbooleanを指定可能で、上記はfalseを指定した以下と同様です。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');},false);
document.getElementById('inner').addEventListener('click',function(){console.log('inner');},false);
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA');},false);
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');},false);
//buttonAをクリックする => buttonA buttonA2 inner outer

第3引数としてtrueを指定すると、実行の順序が逆になります。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');},true);
document.getElementById('inner').addEventListener('click',function(){console.log('inner');},true);
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA');},true);
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');},true);
//buttonAをクリックする => outer inner buttonA buttonA2

イベントリスナーが登録されていると、イベント発生元となった要素を含む親の要素でもそのイベントが実行されます。
そのイベントの実行順序が3つ目の引数で制御できるようになっています。

イベントの伝播はwindowオブジェクトからイベント発生元まで下位へ辿っていくキャプチャーフェーズと、
イベント発生元から上位要素へと辿っていくバブリングフェーズがあります。
つまり、「ouuter -> inner -> buttonA -> inner -> outer」の順序でイベントが伝播し、
前半がキャプチャーフェーズ、後半がバブリングフェーズとなっています。
引数をtrueとするとキャプチャーフェーズでイベントが実行されるため順序が逆となったというわけです。

もちろん混在も可能で、次のようにすると「outer -> buttonA -> inner」と実行がされます。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');},true);
document.getElementById('inner').addEventListener('click',function(){console.log('inner');},false);
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA');});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');});
//buttonAをクリックする => outer buttonA buttonA2 inner 

イベントの伝播はstopPropagation()で止める事ができます。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');});
document.getElementById('inner').addEventListener('click',function(e){console.log('inner');e.stopPropagation();});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA');});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');});
//buttonAをクリックする => buttonA buttonA2 inner

ただし、stopPropagation()だと同じ要素に登録したリスナーの実行は止められません。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');});
document.getElementById('inner').addEventListener('click',function(){console.log('inner');});
document.getElementById('buttonA').addEventListener('click',function(e){console.log('buttonA');e.stopPropagation();});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');});
//buttonAをクリックする => buttonA buttonA2

同じ要素のリスナーも含め、イベントの実行を止めるには、stopImmediatePropagation()を使います。

document.getElementById('outer').addEventListener('click',function(){console.log('outer');});
document.getElementById('inner').addEventListener('click',function(){console.log('inner');});
document.getElementById('buttonA').addEventListener('click',function(e){console.log('buttonA');e.stopPropagation();});
document.getElementById('buttonA').addEventListener('click',function(){console.log('buttonA2');});
//buttonAをクリックする => buttonA

既定の動作、例えばチェックボックスクリック時のチェックを止めたい場合はpreventDefault()で処理を停止できます。

<label><input id="check" type="checkbox" />Check</label>
document.getElementById('check').addEventListener('click',function(e){e.preventDefault();});

addEventListenerの第3引数には、より複雑なオブジェクトをオプションとして指定する事もできます。

document.getElementById('outer').addEventListener('click',function(e){console.log('outer');e.preventDefault();},{
  capture : true , once : true, passive :false,
});
document.getElementById('inner').addEventListener('click',function(e){console.log('inner');e.preventDefault();},{
  capture : true , once : true,  passive :true,
});
document.getElementById('buttonA').addEventListener('click',function(e){console.log('buttonA');e.preventDefault();},{
  capture : true , once : false, passive :false,
});
//buttonAをクリックする(1回目) => outer inner (警告) buttonA
//buttonAをクリックする(2回目) => buttonA

「capture」は第3引数にbooleanを指定したときと同じものです。trueの場合にバブリングフェーズでのイベント実行が行われます。
「once」はtrueの場合、イベントの実行を1回行うとリスナは削除されます。
「passive」はtrueの場合、preventDefault()がリスナで呼ばれるとコンソールに警告が出力されます。

removeEventListener - イベントリスナの削除

removeEventListenerを使うと、指定したイベントからリスナを削除できます。

<div id="outer">
  <div id="inner">
    <button id="buttonA">A</button>
  </div>
</div>
const clickListener1 = function(){console.log('buttonA1');};
const clickListener2 = function(){console.log('buttonA2');};
document.getElementById('buttonA').addEventListener('click',clickListener1);
document.getElementById('buttonA').addEventListener('click',clickListener2);
document.getElementById('buttonA').removeEventListener('click',clickListener1);
//buttonAをクリックする => buttonA2

第2引数を指定すると、キャプチャーフェーズで実行されるリスナであるかが一致する場合にだけ削除が行われます。

const clickListener1 = function(){console.log('buttonA1');};
const clickListener2 = function(){console.log('buttonA2');};
document.getElementById('buttonA').addEventListener('click',clickListener1,false);
document.getElementById('buttonA').addEventListener('click',clickListener2,true);
document.getElementById('buttonA').removeEventListener('click',clickListener1,false);
document.getElementById('buttonA').removeEventListener('click',clickListener2,false);
//buttonAをクリックする => buttonA2
Originally published at javascript-reference.org
ツイッターでシェア
みんなに共有、忘れないようにメモ

portaloo

JavaScript、HTML、CSSの勉強中

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント