JavaScriptのイベントのキャンセル方法についてまとめました。
目次
イベントのキャンセル方法
3つのメソッド
イベントをキャンセルするメソッドは3つあり、それぞれ次のような特徴を持っています。
メソッド | 内容 |
---|---|
preventDefault | アンカータグやチェックボックスなど、要素デフォルトのイベントをキャンセルします。
例えば、アンカータグの場合、リンクがクリックされた際に遷移イベントをキャンセルすることができます。 |
stopPropagation | イベント発生元の親要素に同一のイベントが設定されていた場合、親要素のイベントの実行をキャンセルすることができます。(バブリングの停止)
JavaScriptでは、イベント発生元のイベントが実行されたあと、親要素に同一のイベントが設定されていた場合、そのイベントも実行されます。 イベント発生元のイベントのみ実行したい場合などに使用します。 |
stopImmediatePropagation | 同じ要素に複数の同じイベントが設定されている場合、何もしなければ全てのイベントが実行されますが、stopImmediatePropagation を使用すると、後のイベントをキャンセルすることができます。 |
preventDefault
要素に設定されている、デフォルトのイベント(動作)をキャンセルします。
例えば、アンカー(<a>)がクリックされた際に別ページに遷移する動作をキャンセルしたい場合、次のようにします。
html
1 |
<a id="event-link" href="遷移先のURL" >イベント発生元</a> |
javascript
1 2 3 4 5 6 |
document.getElementById("event-link").addEventListener('click', function(e){ console.log('リンクがクリックされました。'); // デフォルトのイベントをキャンセル e.preventDefault(); }, false); |
アンカータグにイベントリスナーを設定しています。
console.log の後に e.preventDefault でデフォルトのイベントをキャンセルしているため、コンソールにメッセージ “リンクがクリックされました。” が表示されるのみの挙動になります。
stopPropagation
JavaScriptでは、イベントの発生元から親要素に向かって同じ種類のイベントが設定されている場合、全てのイベントが実行されます。
そのため、発生元のイベントのみ実行したい場合などに stopPropagation を使用します。
stopPropagation を実行した後は、親要素に同種のイベントが設定されていても実行されません。
例えば、次のhtml・javascriptの場合
html
1 2 3 4 5 |
<div id="parent2"> <div id="parent1" onclick="showLog()"> <button id="child">イベント発生元</button> </div> </div> |
javascript
1 2 3 4 5 6 7 8 9 10 11 |
document.getElementById("child").addEventListener('click', function(e){ console.log('childイベントが発生しました。'); }, false); document.getElementById("parent2").addEventListener('click', function(e){ console.log('parent2イベントが発生しました。'); }, false); function showLog(){ console.log('parent1イベントが発生しました。'); } |
イベント発生元(id=”child”)の親要素(id=”parent1″、id=”parent2″)にも同じclickイベントが設定されています。
この場合、何もせずに button(id=”child”)をクリックすると、コンソールには、次のように表示されます。
childイベントが発生しました。
parent1イベントが発生しました。
parent2イベントが発生しました。
次に、javascriptの一部を編集して、イベント発生元(id=”child”)のみイベントを実行するようにします。
1 2 3 4 5 |
document.getElementById("child").addEventListener('click', function(e){ console.log('childイベントが発生しました。'); // イベントのバブリングをキャンセル e.stopPropagation(); }, false); |
このようにすることで、コンソールには
childイベントが発生しました。
のみ表示され、以降のバブリングはキャンセルされます。
stopImmediatePropagation
先ほどの、stopPropagation では、親要素へのイベントの伝搬(バブリング)をキャンセルすることができましたが、例えばイベント発生元に、同じイベントが複数設定されている場合は、全て実行されてしまいます。
stopImmediatePropagation を使用すると、使用した以降の全てのイベントがキャンセルされます。(親要素へのイベント伝搬もキャンセルされます)
例えば、1つのbutton要素に、3つのclickイベントが設定されていた場合
html
1 |
<button id="event-btn">イベント発生元</button> |
javascript
1 2 3 4 5 6 7 8 9 10 11 |
document.getElementById("event-btn").addEventListener('click', function(e){ console.log('イベント1が発生しました。'); }, false); document.getElementById("event-btn").addEventListener('click', function(e){ console.log('イベント2が発生しました。'); }, false); document.getElementById("event-btn").addEventListener('click', function(e){ console.log('イベント3が発生しました。'); }, false); |
何もしないと、button(id=”event-btn”)がクリックされると、コンソールには
イベント1が発生しました。
イベント2が発生しました。
イベント3が発生しました。
と表示され、全てのイベントが実行されます。
次に、stopImmediatePropagation を使って、イベント3をキャンセルするようにします。
javascript
1 2 3 4 |
document.getElementById("event-btn").addEventListener('click', function(e){ console.log('イベント2が発生しました。'); e.stopImmediatePropagation(); }, false); |
イベント2でコンソールに出力後、stopImmediatePropagation を使うことで、以降のイベントが全てキャンセルされます。
ただし、stopImmediatePropagationでは、要素デフォルトの挙動はキャンセルできないので、あるイベント以降の全てのイベントをキャンセルする場合は、stopImmediatePropagation と preventDefault を使用します。
その他
上記3つのメソッド以外にもイベントをキャンセルする方法があります。
それは、イベントハンドラで return false を使うことでイベントをキャンセルすることができます。
例えば、preventDefault を使用してアンカータグの遷移イベントをキャンセルした方法を、イベントハンドラでは、次のように行います。
html
1 |
<a href="遷移先のURL" onclick="showLog(); return false;">イベント発生元</a> |
javascript
1 2 3 |
function showLog(){ console.log('clickイベントが発生しました。'); } |
htmlの onclick で showLog() を呼び出した後に、return false; を行なっています。
このように、イベントハンドラで、return false; を返すことで要素デフォルトのイベントをキャンセルすることもできます。
まとめ
イベントのキャンセル方法についてまとめました。
JavaScriptでは、イベントの発生元から、親要素に向かってイベントが伝播(バブリング)するため、油断すると思わぬ不具合になる可能性があります。
もし、以降のイベントを明示的にキャンセルする場合は、次のパターンでキャンセルすると安全かもしれません。
要素デフォルトのイベントがない
・stopImmediatePropagation
を使用して以降のイベントをキャンセル
要素デフォルトのイベントがある
・stopImmediatePropagation
・preventDefault
を使用して以降のイベントをキャンセル