6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jQueryの.triggerとネイティブイベント

Posted at

jQuery離れを進めようと、少しずつ既存コードをネイティブDOMで書き直しているような箇所もあったりする1のですが、混在すると特有なトラブルに見舞われたりもします。

TL; DR

  • jQueryの.triggerで起きるのは、「jQuery上のイベント」、「on***」、「(起こせるものは)標準操作」だけ
  • addEventListenerでセットしたイベントを駆動させることはない
  • ただ、clickでは「標準操作」がイベントも引き起こす

発生した問題

jQueryで書いていたものを徐々に切り替えていたのですが、jQueryでtriggerしたはずのイベントが、addEventListenerで拾えない、ということが発生しました。

jQueryのイベントシステム

jQuery 1.0が出た頃は、ブラウザのDOMへの対応状況も、現代から見ればめちゃくちゃと言っていい状況でした。そんな中でバブリングなどをきちんと実現するために、jQueryはイベントシステムを自前で構築しています。これは、最新版の3系列でも同じ状況です。

そして、triggerのコードを追いかけてみたところ、以下のような動作になっていました。

  1. DOMの仕様のように、DOMツリーの上からたどって目的の要素を抽出して2、そこについているjQueryイベントとon***を実行していく
  2. ターゲットから上位に戻っていって、引き続きイベントを実行していく
  3. .preventDefault()されていなかった場合、(存在すれば)ネイティブな動作をさせるメソッド(focus()click()submit()など少数派です)を実行する

ということで、addEventListenerでセットされたものを呼ぶのに必要なdispatchEventなどは、どこにもありませんでした。なお、ネイティブのclick()だけは例外的に、「イベントも実行する」メソッドになっていますので、これだけは実行されます。

結論

jQueryのイベントはjQueryでしか受けられないので、カスタムイベントで状態の受け渡しをする系を作っているような場合は、先にイベントをtriggerする側をネイティブに切り替えないと、イベントを拾えなくなります。なお、jQueryもネイティブのaddEventListenerでイベントを拾っていますので、逆に「ネイティブDOMでdispatchEventしたイベントをjQueryのハンドラで拾う」ことは、問題なく可能です。

脚注

  1. SPA移行が現実的でない環境なので、複雑なウィジェットはRiotに移して、そこまで大掛かりにならない部分や、つなぎ目はネイティブに実装、という感じで進めています。

  2. なお、jQueryにキャプチャフェーズはありません。

6
5
1

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
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?