LoginSignup
4

More than 5 years have passed since last update.

Element.closestで作る簡単Event Delegation

Last updated at Posted at 2017-11-22

やりたいこと

jQueryのon関数に代表される、子孫Elementのイベント監視をブラウザのNativeなWeb APIだけで実現したいです。

JSFiddle

なお、この記事の想定読者は、2年半前の自分です。

jQuery Event Delegation の代替えを考える - Qiita

設計

引数

jQueryでは

  • 親Element
  • イベント
  • 要素を特定するselector文字列

で監視したいイベントを特定します。
引数はこのまま使います。

Element.closest

現代的なブラウザはElement.closest APIをサポートしています。
IEはサポートしていません。

このAPIは、自Elementまたは祖先Elementのうちで、selecotrに合致する、もっとも近いElementを返します。

仕組み

子Elementで発生したイベントはバブリングフェーズで親Elementに渡ってきます。
その時Event.targetプロパティに、イベントが発生したElementが格納されています。
そのElementのclosestメソッドを使ってselectorと一致するか確認します。

実装

function delegate(element, event, selector, callback) {
  element.addEventListener(event, (e) => {
    if (e.target.closest(selector)) {
      callback(e)
    }
  })
}

使い方

delegate(document, 'mouseover', 'h2', e => console.log('hi', e))

jQuery.onとの挙動の違い

Element.closestを使っているためのjQuery.onと微妙な違いがあります。
個人的には、Elementの子にSpanなどのElementが入っていても、イベントが発火してほしいので、今の実装が気に入っています。

次のElementで

<div class="class1">
  Hello <span>World</span>!
</div>

HelloでもWorldでもイベントが発火します。

selectorの子要素を除外する場合

個別のcallback関数で除外したい場合は、callback関数内で

event.target.classList.contains(.class1)

などで、フィルタリングしましょう。

完全なjQuery互換にしたい場合

Element.closestの代わりにElement.mathcesを使って実装しましょう。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4