やりたいこと
jQueryのon関数に代表される、子孫Elementのイベント監視をブラウザのNativeなWeb APIだけで実現したいです。
なお、この記事の想定読者は、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を使って実装しましょう。