jQuery:同じイベントの複数のハンドラー


137

2つのイベントハンドラーを同じ要素の同じイベントにバインドするとどうなりますか?

例えば:

var elem = $("...")
elem.click(...);
elem.click(...);

最後のハンドラーは「勝ち」ますか、それとも両方のハンドラーが実行されますか?

回答:


168

両方のハンドラーが実行され、jQueryイベントモデルでは1つの要素で複数のハンドラーが許可されるため、後のハンドラーが古いハンドラーをオーバーライドすることはありません。

ハンドラーは、バインドされた順序で実行されます。


1
ネイティブの方法で何が起こりますか?そしてネイティブはどのように特定のものを削除する方法を知っていますか?
SuperUberDuper 2015

1
DOMレベル3(HTML 5仕様を参照)によると、イベントハンドラーは登録された順序で実行されます-w3.org/TR/DOM-Level-3-Events/#event-phaseおよびw3.org/TR/ 2014 / REC-html5-20141028 /…。イベントハンドラーは、登録されたハンドラーへの参照を渡すことで削除できます
Russ Cam

@RussCam同じハンドラーが複数回バインドされている場合、jQuery('.btn').on('click',handlerClick);実際.offには何もせずにさまざまな場所で呼び出されると言うだけでどうなりますか?
techie_28 2016年

jQueryUIウィジェットファクトリウィジェットの場合、ハンドラーをオプションとして設定した場合、これは当てはまりません。古いハンドラーと新しいハンドラーの両方を呼び出すには、bindメソッドを使用する必要があります。詳細については、これを参照してください。learn.jquery.com/jquery-ui/widget-factory/...
マイケルScheper

@MichaelScheperは回答を編集し、追加情報で更新してください
Russ Cam

36

2つのハンドラーfgがあり、それらが既知の固定された順序で実行されることを確認してから、単にそれらをカプセル化するとします。

$("...").click(function(event){
  f(event);
  g(event);
});

このように、(jQueryの観点から)fgを指定された順序で呼び出すハンドラーは1つだけです。


3
+1、関数内のカプセル化が進むべき道です。さらに、トリガーされるイベントを制御するために、ハンドラー関数内にさらに優れた条件ロジックを含めることができます。
ゴードンポッター、

シーケンスがプログラムによって決定されるハンドラーのコレクション。
アーロンブレンクシュ14年

17

jQueryの.bind()は、バインドされた順序で起動します。

イベントが要素に到達すると、その要素のそのイベントタイプにバインドされているすべてのハンドラーが呼び出されます。複数のハンドラーが登録されている場合、それらは常にバインドされた順序で実行されます。すべてのハンドラが実行された後、イベントは通常のイベント伝播パスに沿って続行されます。

ソース:http : //api.jquery.com/bind/

jQueryの他の関数(例:)はの.click()ショートカット.bind('click', handler)であるため、それらもバインドされた順序でトリガーされると思います。


11

チェーンを使用してイベントを順番に実行できる必要があります。例:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

以下のコードも同じことをしていると思います

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

出典:http : //www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFMはまた言います:

イベントが要素に到達すると、その要素のそのイベントタイプにバインドされているすべてのハンドラーが呼び出されます。複数のハンドラーが登録されている場合、それらは常にバインドされた順序で実行されます。すべてのハンドラが実行された後、イベントは通常のイベント伝播パスに沿って続行されます。


1
そのコードもその記事もハンドラー実行の順序を定義していません。はい、これはイベントバインディングが発生する順序ですが、イベントハンドラーが呼び出される順序はまだ正式には定義されていません。
クレセントフレッシュ

えっ?「クリックイベントが発生すると、最初のイベントハンドラが呼び出され、次に2番目、3番目のイベントハンドラが呼び出されます。」不明ですか?
anddoutoi 09/09/29

そして、はい、私は公式の記録がこれを定義していないことを知っています、そしてPPKはすでにイベントの実行がランダムであることを証明しましたが、おそらくjQueryがこれを修正しました^^
anddoutoi

ああ、その文章を逃した。実際、著者は誤解されています。jQueryはこれを「修正」していません。仕様では正式に順序が定義されていないため、技術的には修正の必要はありません。
クレセントフレッシュ

5
@CrescentFresh:返信が遅くなって申し訳ありません。質問を見ただけですが、リンクを指定してください。これはjQueryの公式ドキュメントであり、明確に次のように記載されていますWhen an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
Razort4x

2

両方のハンドラーが呼び出されます。

インラインイベントバインディング(など"onclick=...")を考えているかもしれませんが、大きな欠点は、イベントに対して1つのハンドラーしか設定できないことです。

jQueryは、DOMレベル2のイベント登録モデルに準拠しています

DOMイベントモデルでは、1つのEventTargetに複数のイベントリスナーを登録できます。これを実現するために、イベントリスナーは属性値として保存されなくなりました


@リッチ:順序は公式には未定義です。
クレセントフレッシュ

2

Stephan202のカプセル化と複数のイベントリスナーという2つの方法を使用して、正常に機能するようにしました。私には3つの検索タブがあります。それらの入力テキストIDを配列で定義しましょう。

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

searchtab1の内容が変更された場合、searchtab2とsearchtab3を更新します。カプセル化のためにこのようにしました:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

複数のイベントリスナー:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

私は両方の方法が好きですが、プログラマーはカプセル化を選択しましたが、複数のイベントリスナーも機能しました。テストにはChromeを使用しました。


1

1つのハンドラーが次々と発生することを保証する回避策があります。2番目のハンドラーをコンテナー要素にアタッチし、イベントをバブルアップさせます。コンテナーに接続されたハンドラーで、event.targetを調べて、目的のものである場合は何かを行うことができます。

粗野かもしれませんが、確実に機能するはずです。


0

jqueryは複数のイベントハンドラーを許可するため、両方のハンドラーを実行します。サンプルコードを作成しました。あなたはそれを試すことができます

デモ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.