[解決済み] jQueryのイベントハンドラは、常にバインドされた順に実行されます - これを回避する方法はありますか?重複
質問
jQueryのイベントハンドラは、常にバインドされた順番で実行されるのが煩わしい場合があります。例えば
$('span').click(doStuff1);
$('span').click(doStuff2);
をクリックすると
doStuff1()
が発生し、その後に
doStuff2()
.
doStuff2()をバインドする際に、オプションで の前に doStuff1()を使っていますが、これを簡単に実行する方法はないようです。
ほとんどの人は、このようにコードを書けばいい、と言うのでしょうね。
$('span').click(function (){
doStuff2();
doStuff1();
});
しかし、これは単純な例であり、実際にはそうすることが常に便利であるとは限りません。
イベントをバインドしたいとき、バインド先のオブジェクトがすでにイベントを持っている場合があります。この場合、新しいイベントを他の既存のイベントより先に発生させたいだけかもしれません。
では、jQueryでこれを実現する最善の方法は何でしょうか?
どのように解決するのですか?
回答を更新しました。
jQueryは1.8でイベントが保存される場所を変更しました。内部APIをいじくり回すのがなぜ悪い考えなのか、おわかりいただけたでしょうか :)
新しい 内部 DOMオブジェクトのイベントにアクセスするAPIは、各インスタンスに縛られることなく、グローバルなjQueryオブジェクトを通して利用可能で、第1パラメータとしてDOM要素、第2パラメータとしてキー(私たちは "events" )が渡されます。
jQuery._data(<DOM element>, "events");
というわけで、jQuery 1.8用に修正したコードは以下の通りです。
// [name] is the name of the event "click", "mouseover", ..
// same as you'd pass it to bind()
// [fn] is the handler function
$.fn.bindFirst = function(name, fn) {
// bind as you normally would
// don't want to miss out on any jQuery magic
this.on(name, fn);
// Thanks to a comment by @Martin, adding support for
// namespaced events too.
this.each(function() {
var handlers = $._data(this, 'events')[name.split('.')[0]];
// take out the handler we just inserted from the end
var handler = handlers.pop();
// move it at the beginning
handlers.splice(0, 0, handler);
});
};
そして、ここでは プレイグラウンド .
オリジナルの回答
Seanが発見したように、jQueryはすべてのイベントハンドラを要素の
data
インターフェースを通して公開します。具体的には
element.data('events')
. これを使えば、いつでも特定の位置に任意のイベントハンドラを挿入できる簡単なプラグインを書くことができます。
ここに、リストの最初にハンドラを挿入する簡単なプラグインがあります。任意の位置に項目を挿入するために、これを簡単に拡張することができます。これは単なる配列操作です。しかし、私はjQueryのソースを見ていないし、jQueryのマジックが起こるのを見逃したくないので、通常、ハンドラを追加するには
bind
を使ってハンドラを追加し、それから配列をシャッフルします。
// [name] is the name of the event "click", "mouseover", ..
// same as you'd pass it to bind()
// [fn] is the handler function
$.fn.bindFirst = function(name, fn) {
// bind as you normally would
// don't want to miss out on any jQuery magic
this.bind(name, fn);
// Thanks to a comment by @Martin, adding support for
// namespaced events too.
var handlers = this.data('events')[name.split('.')[0]];
// take out the handler we just inserted from the end
var handler = handlers.pop();
// move it at the beginning
handlers.splice(0, 0, handler);
};
つまり、例えばこのマークアップの場合、次のように動作します ( この例 ):
<div id="me">..</div>
$("#me").click(function() { alert("1"); });
$("#me").click(function() { alert("2"); });
$("#me").bindFirst('click', function() { alert("3"); });
$("#me").click(); // alerts - 3, then 1, then 2
しかし
というのは
.data('events')
は私が知る限りでは公開 API の一部ではないので、jQuery の更新により、例えば添付イベントの基本的な表現が配列から他のものに変更された場合、あなたのコードが壊れる可能性があります。
免責事項: 何でも可能なので :) 、これがあなたの解決策です。しかし、私なら既存のコードをリファクタリングする側に回ります。
関連
-
[解決済み] クラスメソッド内の "this "をタイプスクリプトで記述する
-
[解決済み] 動的に生成された要素にイベントバインディングを行うか?
-
[解決済み] jQueryのイベントハンドラを削除する最良の方法?
-
[解決済み] jQuery checkbox checked state changed event
-
[解決済み] 複数のクラスを削除する(jQuery)
-
[解決済み] JavaScript / jQuery のイベントバインディングを Firebug などでデバッグするには?
-
[解決済み] jQueryで要素にバインドされたイベントを見つけることはできますか?
-
[解決済み] ドロップダウンメニューが内部でクリックされたときに閉じないようにする
-
[解決済み】jQueryのテンプレートエンジン【終了しました
-
[解決済み】jQueryでRSSをパースする。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JavaScript - 二重引用符のエスケープ
-
[解決済み] jQuery 複数のイベントで同じ関数を起動する
-
[解決済み] jQueryを使って「Please Wait, Loading...」というアニメーションを作成するにはどうすればよいですか?
-
[解決済み] Twitter Bootstrapのモーダルウィンドウを閉じないようにする
-
[解決済み] jQueryを使用してCSSのdisplay noneまたはblockプロパティを変更するにはどうすればよいですか?
-
[解決済み] チェックボックスがチェックされた場合のjQuery
-
[解決済み] jQuery: テキストで要素を検索する
-
[解決済み] jQueryでイベントハンドラが要素にバインドされているかどうかをテストする [重複] 。
-
[解決済み] jQueryで<input type="text">のonchangeを実装するには?
-
[解決済み] jQueryで束縛されたイベントを順番に処理する方法