Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

Better Stimulusガイド 04: イベントリスナーの追加・削除はStimulusで行う(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

🔗 1. マークアップにグローバルなイベントを登録する

Bad

connect() {
  document.addEventListener(...);
}

Good

<div data-controller="gallery" data-action="resize@window->gallery#layout">...</div>
layout(e) {
  ...
}

そうする理由

イベントリスナーの追加や削除はStimulusが行うからです。

この方法が使えない場合

コントローラのコードはマークアップを前提としていますが、Stimulusコントローラをライブラリとして作成する場合はこの前提が使えないことがあります。その場合は、必ずdisconnectでイベントリスナーを登録解除してください。

その理由

Stimulusのコントローラはconnectdisconnectを任意の回数実行できます。connectで追加されたイベントリスナーがdisconnectでクリーンアップされないと、要素に対して複数のイベントリスナーが存在することになり、イベントリスナーのコールバックが1度ではなく複数回実行されてしまいます。

🔗 2. イベントリスナーをconnectdisconnectでクリーンアップする

Bad

connect() {
  document.addEventListener("click", this.findFoo.bind(this))
}

disconnect() {
  document.removeEventListener("click", this.findFoo.bind(this))
}

findFoo() {
  console.log(this.element.querySelector("#foo"))
}

Good

connect() {
  this.boundFindFoo = this.findFoo.bind(this)
  document.addEventListener("click", this.boundFindFoo)
}

disconnect() {
  document.removeEventListener("click", this.boundFindFoo)
}

findFoo() {
  console.log(this.element.querySelector("#foo"))
}

最初の例がよくない理由

ある関数で.bind()が呼び出されると、新たに関数が1個作成されます。つまり.bind()を2回呼び出せば、addEventListenerremoveEventListenerがそれぞれ呼び出す関数の参照が異なってしまい、イベントが削除されません。
イベントリスナーの追加と削除では、同じ.bind()関数の参照が使われるようにしてください。

参考資料

関連記事

Better Stimulusガイド:アーキテクチャ1: アプリケーションコントローラ(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。