解説
リンクの移動と親への通知を分ける:preventDefaultとstopPropagationの違い
リンクの既定動作とイベントの伝播を、二つのスイッチで比較。preventDefault・stopPropagationの役割と、止めない処理を作例で確認。

リンクを押したとき、移動を止めたいのか、親へクリックが伝わるのを止めたいのか。JavaScriptのpreventDefault()とstopPropagation()は、別のことをするメソッドだよ。
今回は外部へ移動しない、作例内の目印へ進むリンクを使う。リンク側と親側の回数、URLの末尾の目印を一緒に確認しよう。
preventDefaultは、キャンセルできる既定動作を止める
link.addEventListener("click", event => {
event.preventDefault();
});
リンクには、指定した場所へ移動するブラウザの既定動作がある。今回のclickでpreventDefaultを呼ぶと、その移動を止められる。
ただし、親へクリックが伝わることまで止める指定ではない。同じ操作を親で受け取るリスナーがあれば、そちらは動く場合があるよ。
stopPropagationは、イベントが伝わるのを止める
link.addEventListener("click", event => {
event.stopPropagation();
});
こちらは、イベントがほかの要素へ伝播するのを止める。今回の作例ではリンクから親のボックスへ伝わるバブリングを止め、親の回数が増えなくなる。
リンクの移動は既定動作なので、これだけでは止まらない。同じ要素にある別のリスナーまで止めるstopImmediatePropagationとも、役割が違うよ。
二つのスイッチで比べよう
| 移動を止める | 親への伝播を止める | 作例の結果 |
|---|---|---|
| オン | オフ | 目印へ移動しない・親の回数は増える |
| オフ | オン | 目印へ移動する・親の回数は増えない |
| オン | オン | 目印へ移動しない・親の回数も増えない |
作例は初めに、移動を止めるほうだけがオン。リンクを押した回数は、いずれの組合せでも増える。呼び出したリスナー自体が、なかったことになるわけではないんだ。
「最初から試す」は回数、スイッチ、作例内URLの目印を戻す。ほかのページへ移動したり、ブラウザ全体の履歴を削除したりはしないよ。
どんなイベントでもキャンセルできるわけではない
preventDefaultが効くには、対象の動作がキャンセル可能である必要がある。passiveなリスナーから呼んでも、既定動作を止められない場合がある。
今回確認するのは、通常のリンクのclickと、バブリング段階の親リスナー。キャプチャ段階ですでに動いた処理まで、あとから取り消せるという説明ではないよ。
先に、止めたい理由を確認する
リンクをボタンの代わりにして毎回移動を止めるより、そもそも移動なのか操作なのかを考えることも大切。フォームなら、クリックだけでなくsubmitの扱いが必要になる場面もある。
編集部ではChromiumでスイッチの組合せ、目印への移動、親とリンクの回数、リセットを確認した。対象を読むにはtargetとcurrentTarget、要素の選択はリンクとボタンも参考になるよ。
動かしてみよう:移動と親への伝播
二つのスイッチを切り替え、作例内の目印と親のクリック回数を比べよう。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。