私のページには、ビューを表すマークアップのチャンクと、そのビューに関連付けられている JS コントローラー関数があります。(これらは Angular ですが、それは問題ではないと思います。) コントローラー コードは、アプリの別の場所から発生したカスタム イベントをリッスンし、コントローラー固有のロジックでそのイベントを処理します。
私の問題は、コントローラーのイベント ハンドラーが何度もアタッチされていることです。ビューが再アクティブ化されるたびにアタッチされ、カスタム イベントが発生するたびにハンドラーが複数回実行されます。ハンドラーをイベントごとに 1 回だけ実行したい。
.off()
ハンドラーをバインドする前にバインドを解除するために使用しようとしました。.one()
ハンドラーが 1 回だけ実行されるようにしました。here$.proxy()
との相互作用について読んだ後、試してみました。.off()
ここに私のコードのスケッチがあります:
// the code inside this controller is re-run every time its associated view is activated
function MyViewController() {
/* SNIP (lots of other controller code) */
function myCustomEventHandler() {
console.log('myCustomEventHandler has run');
// the code inside this handler requires the controller's scope
}
// Three variants of the same misbehaving event attachment logic follow:
// first attempt
$('body').off('myCustomEvent', myCustomEventHandler);
$('body').on('myCustomEvent', myCustomEventHandler);
// second attempt
$('body').one('myCustomEvent', myCustomEventHandler);
// third attempt
$('body').off('myCustomEvent', $.proxy(myCustomEventHandler, this));
$('body').on('myCustomEvent', $.proxy(myCustomEventHandler, this));
// all of these result in too many event attachments
};
// ...meanwhile, elsewhere in the app, this function is run after a certain user action
function MyEventSender() {
$('body').trigger('myCustomEvent');
console.log('myCustomEvent has been triggered');
};
アプリ内をクリックして面倒なビューに 5 回切り替えてから、実行されるアクションを実行するMyEventSender
と、コンソールは次のようになります。
myCustomEvent has been triggered
myCustomEventHandler has run
myCustomEventHandler has run
myCustomEventHandler has run
myCustomEventHandler has run
myCustomEventHandler has run
次のようにするにはどうすればよいですか。
myCustomEvent has been triggered
myCustomEventHandler has run
???