普段jQueryばかり書いている人間が、イベントキャンセル処理を通常のJavaScriptで書こうとしてハマったのでメモ。
概要
通常のJavaScriptでイベントをキャンセルしたい場合は、addEventLinstenerでpreventDefault()
とstopPropagation()
を呼び出そう。
問題
jQueryであれば以下のようにreturn false
すれば、バブリング(親要素のalert)およびデフォルトアクション(画面遷移)を停止できるが
<div class="parent">
<a href="https://~~" class="child">テスト</a>
</div>
$('.parent').on('click' ,function(){
alert('parent');
});
$('.child').on('click' ,function(){
alert('child');
return false;
});
通常のJSのaddEventLinstenerで同じようreturn false
してもデフォルトアクションをキャンセルできない。
以下の書き方だと親要素のalertも表示され、画面遷移もしてしまう。
const parent = document.querySelector('.parent');
const child = document.querySelector('a');
parent.addEventListener("click", function(){
alert("parent");
});
child.addEventListener("click", function(e){
alert("child");
return false;
});
解決策
js側でreturn false
の代わりにpreventDefault()
とstopPropagation()
を呼び出す。
child.addEventListener("click", function(e){
alert("child");
e.preventDefault(); //バブリングの停止
e.stopPropagation(); //イベントキャンセル
});
ちなみにhtml側のonclickで以下のようにreturn falseを指定すれば画面遷移はキャンセルできるが親要素のイベントは走ってしまう。
<div class="parent">
<a href="https://~~" class="child" class="child" onclick="return false;">テスト</a>
</div>
こちらの記事によると、通常のJavaScriptでreturn false
した場合にはpreventDefault()
のみが呼ばれるとのこと。
jQueryのreturn false
ではreventDefault()
とstopPropagation()
の両方が呼ばれる。
まとめ
コードの可読性を上げるためにも、通常のJavaScriptでもjQueryでもイベント伝播を停止する際はpreventDefault()
とstopPropagation()
を使用し、明確に動作の意図を伝えたほうが良さそう。
参考
JavaScriptでのイベントキャンセルの落とし穴 - Linkers Tech Blog
addEventListener() のリスナーでreturn falseしてもイベントはキャンセルできない - いろいろ