JavaScriptのイベント伝播
今日はaddEventListener
の引数について調べていたら、
イベント伝播?バブリング?キャプチャリング??!と知らないことだらけだったので、
調べてまとめてみます!
まず大前提:イベントは伝播するということ
<!--HTML-->
<div id="parent"> <!--親-->
<div id="child"> <!--子-->
</div>
</div>
このように親子関係になっている二つの要素に、イベントリスナを登録します。
document.getElementById('parent').addEventListener('click',()=>{
alert('親だよ');
});
document.getElementById('child').addEventListener('click',()=>{
alert('子だよ');
});
このように親子関係で同じイベントリスナを登録し子をクリックすると、親のイベントも一緒に発動します。
イベントの伝播の道筋
イベントが発生したら、以下の道筋を辿ります。
①キャプチャーフェーズ
windowからその子へ、そしてその子へ、、と順従に目的のノードに向かってイベントが走るフェーズ。
②ターゲットフェーズ
イベントが発生した要素にイベントが伝わるフェーズ
③バブリングフェーズ
イベント発生元から親へ向かって順々にイベントが走るフェーズ。
え!二回も走ってるの!?
と思いました。じゃあどっちでイベント伝播してるの?と。
addEventListenerの第三引数
それを定めることができるのがaddEventListener
の第三引数らしいです。
element.addEventListener('click',event,true/false);
true
・・・キャプチャーフェーズ時に発火する。(つまり親から先に発火)
false
・・・バブリングフェーズ時に発火する・(つまり子から先に発火)←初期値
これでどちらから発火させるか?をコントロールすることができます。
なんならキャプチャーフェーズ時とバブリングフェーズ時に二回発火も可能みたいです。
使い方によっては面白いことができそうです。
伝播やめて!!!
stopPropagation()
を使えばいいそうです。
document.getElementById('parent').addEventListener('click',()=>{
alert('親だよ');
});
document.getElementById('child').addEventListener('click',(e)=>{
e.stopPropagation();
alert('子だよ');
});
これで子をクリックしても、親のイベントリスナがバブリングすることがなくなります。
おまけ:登録したイベントリスナを無効にしたい
removeEventListener
・・・addEventListenerで登録したイベントリスナーを削除する。
こいつを使えばおっけーです。ただし、addEventListenerの第二引数を無名関数にすると使えないので注意!
function message() {
console.log('Erase me!');
}
element.addEvenetListener('click',message) //登録
element.removeEventListener('click',message) //削除