Javascript addEventListener イベント伝播
2013.04.07
この記事は最終更新日から1年以上が経過しています。
Javascriptを用いたスマートフォンUIや、webアプリケーションなどを制作していく際、タッチスタートのイベントだったり、タッチムーブのイベントだったりと、domにイベントを色々と登録し、イベントを発生させていくかと思うのですが、その際、イベントを登録する為の関数、addEventListenerを用いてイベントを持たせていくのですが、a要素などにイベントを追加し、何か処理を行おうとすると、クリックやタッチをすると、通常の動作のリンク先に飛ぶ。という動作になったりします。
この動作を回避するためには、event.preeventDefault();を用いて、通常の動作(リンク)を無効にします。
event.preeventDefault();
また、現在のイベントを止めるときは、stopPropagation();でのさらなる伝播を止める事ができます。
event.stopPropagation()
さあ、ここでイベントの伝播とは?という話になるのですが、イベントの伝播とはDOM上でイベントが発生した際の伝わり方。といったところでしょうか。
主に使うのはCaptureフェーズと、Bubblingフェーズの2種類であり、これはイベントを登録する際のaddEventListenerの第3引数で指定することが可能となっております。
1.Captureフェーズ:ルートオブジェクト(HTMLだとDocumentオブジェクト)からイベントが発生したオブジェクトに向かって子孫要素をたどっていき、順にイベントハンドラに対し処理をディスパッチしていく。
2.Bubblingフェーズ: イベントが発生したオブジェクトの直接の親要素から、その子孫(ルートオブジェクト側)に向かってたどっていき、順にイベントハンドラに対し処理をディスパッチしていく。
3.Targetフェーズ: イベントが発生したオブジェクト上のイベントハンドラに対し処理をディスパッチする。
図で表すと以下の様な感じとなります。
false:BubblingフェーズまたはTargetフェーズ
document.getElementById("btn").addEventListener("click", hoge, false);
true:Captureフェーズ(use Cature)
document.getElementById("btn").addEventListener("click", hoge, true);
このようにaddEventListenerの第3引数のuseCapture を true
にすることによって、Captureフェーズに切り替えることができます。この引数は全てのブラウザで省略可能ではないのですが、省略した場合はfalseとなり、Bubblingフェーズとなります。
通常、falseに設定して利用することが多いです。
というのも、trueつまり、Captureフェーズにすると、同typeのイベントを登録した要素が存在した際、同イベントを発生させた要素の親要素であるイベントが先に発生しまう結果となります。
上記の例で言うと、divとpにclickイベントを追加し、divをクリックするとアラート「div」、pをクリックするとアラート「p」を発生。
pをクリックした際、Bubblingフェーズだと、p→divとイベントの伝播が行われるが、
Captureフェーズだと、div→pとイベントの伝播が行われる。
この事を避けるためでもある。
テスト
http://webcyou.com/demo/js/event/eventlistener.html
stopPropagation();
イベントの伝播について分かったと思いますので、元に戻り、stopPropagation()についてですが、
これらのイベントの伝播を中止することができます。
この、stopPropagation()を先程のテストのdivに追加してみました。
Bubblingフェーズだと、p→divとイベントの伝播行われていますが、
Captureフェーズだと、divの時点でイベント伝播が終了しているのが確認できます。
テスト
http://webcyou.com/demo/js/event/eventlistener02.html
ちょっと凝ったUI制作や、webアプリケーションを開発する際は、複数addEventListenerを使用していくこともあって、このことも考えておくとよろしいかと思います。
ではでは。