addEventListener()の第3引数の意味とかをちゃんと理解する為のメモ
Web上でUIをマジメに作ろうとするとイベントの仕組みをちゃんと理解しておく必要がある。
jQueryとか便利なライブラリつかえばある程度簡単にできるんだろうけど、いろいろ制約あってそれらのライブラリが使えない場合もあるので、ちゃんと理解するためにメモしておく。
イベント伝播の順番
W3Cのドキュメントに分かりやすい図があったので引用する。
Document Object Model Events
- The capture phase: the event is dispatched to the target's ancestors from the root of the tree to the direct parent of the target node.
- The target phase: the event is dispatched to the target node.
- The bubbling phase: the event is dispatched to the target's ancestors from the direct parent of the target node to the root of the tree.
イベントは以下のような順番でDOMの中を伝播していく
- Captureフェーズ: ルートオブジェクト(HTMLだとDocumentオブジェクト)からイベントが発生したオブジェクトに向かって子孫要素をたどっていき、順にイベントハンドラに対し処理をディスパッチしていく。
- Targetフェーズ: イベントが発生したオブジェクト上のイベントハンドラに対し処理をディスパッチする。
- Bubblingフェーズ: イベントが発生したオブジェクトの直接の親要素から、その子孫(ルートオブジェクト側)に向かってたどっていき、順にイベントハンドラに対し処理をディスパッチしていく。
上記からわかるとおり、DOM上でイベントが発生したとき、オブジェクトによってはイベントが到達するタイミングが2回存在することがわかる。
addEventListener() の第3引数でイベントを受け取るタイミングを指定する
accEventListener()の第3引数であるuseCaptureの設定によって、以下のようにイベントをどのフェーズでディスパッチするかを指定することができる。
- true: Captureフェーズ
- false: Targetフェーズ, あるいは Bubblingフェーズ
イベントの伝播をせき止める Event.stopPropagation()
また、 Event.stopPropagation() を呼び出すと、イベントの伝播をそこで停止して、以降のノードへの伝播をせき止めることができる。
たとえば以下の図のように、子要素でイベントが発生したとき、その親要素でイベントを横取りするような使い方もできる。
嫌な親ですね